• 【学习笔记】全排列


    今天模拟赛最后一题暴力骗分没骗到,特此下定决心搞懂全排列

    1.全排列的定义和公式:

    从n个数中选取m(m<=n)个数按照一定的顺序进行排成一个列,叫作从n个元素中取m个元素的一个排列。由排列的定义,显然不同的顺序是一个不同的排列。从n个元素中取m个元素的所有排列的个数,称为排列数。从n个元素取出n个元素的一个排列,称为一个全排列。全排列的排列数公式为n!,通过乘法原理可以得到。

    2.时间复杂度:

    n个数(字符、对象)的全排列一共有n!种,所以全排列算法至少时间O(n!)
    的。如果要对全排列进行输出,那么输出的时间要O(n∗n!)

    ,因为每一个排列都有n个数据。所以实际上,全排列算法对大型的数据是无法处理的,而一般情况下也不会要求我们去遍历一个大型数据的全排列。

    例题luogu全排列问题


    法1:STL大法好!

    #include<bits/stdc++.h>
    #define rep(a,b,c) for(int a=b;a<=c;a++)
    using namespace std;
    
    int x[11];
    int n;
    int main()
    {    
    	scanf("%d",&n);
    	
    	rep(i,1,n)
    	{
    		x[i]=i,
    		printf("    %d",i);
    	} 
    		
        while(next_permutation(x+1,x+1+n))
    	{
    		printf("
    ");
    		
    		rep(i,1,n) 
    			printf("    %d",x[i]);
    	}
    	return 0;
    }
    

    法2 dfs

    #include<bits/stdc++.h> 
    using namespace std;
    
    int n;
    int ans[15];//保存当前的方案
    int use[15];
    
    void dfs(int x)//X表示当前搜索到那个数
    {
        if(x>n)
    	{//如果N位都搜索完了,就输出方案并返回
            for(int i=1;i<=n;i++)
                printf("%5d",ans[i]);
            printf("
    ");
            return;
        }
        
        for(int i=1;i<=n;i++)//从小到大枚举
    	    if(!use[i])
    		{
    	        ans[x]=i;//保存到方案中
    	        use[i]=1;
    	        dfs(x+1);
    	        use[i]=0;
    	    }
    }
    
    int main()
    {
        scanf("%d",&n);
        dfs(1);
    }
    

    法3 状压dp

    震惊!蒟蒻复制了大佬的题解!

    #include<bits/stdc++.h>
    using namespace std;
    //PS:这里就不用标记数组啦!s就相当于是标记数组了呢。)
    
    int n,lg[1030],ans[10];
    
    void dfs(int i,int s)//在dfs里加上一个形参s,是状态压缩的二进制数,1代表当前位置可以搜,反之是0。
    {
        if(i>n)
    	{
    		for(int p=1;p<=n;p++)
                printf("%5d",ans[p]);
    		return;
    	}
        
    	for(int ss=s;ss>0;ss-=ss&(-ss))//改一下递归部分的for(创建一个临时变量ss,替代当前一层的s;条件是s不为0;去掉ss的最后一位;)
        {
            int temp=ss&(-ss);//因为懒,就创建了一个临时变量。普及一下:一个数a求它二进制数的最右面一位1,就这么求:a&(-a)
            ans[i]=lg[temp];//因为状态压缩的每一位的数值就是2的(那一位)位数次方,所以lg数组起到了把位数上的值转变成位数的作用。
            dfs(i+1,s-temp);//这里递归时s减掉最后一位就行了。
        }
    }
    int main()
    {
        scanf("%d",&n);
        lg[1]=1;
        for(int i=2;i<=n;i++)
            lg[1<<(i-1)]=i;//创建一个数组,下标是二的n次方的位置里存的是n;1<<几就是2的几次方。
    		//(举个例子:下标是32的位置里存的是5,下标是1024的位置存的是10)
        dfs(1,(1<<n)-1);//第一次递归时所有位置都没搜
        return 0;
    }
    
  • 相关阅读:
    三、sersync+rsync实现服务器文件实时同步
    二、Linux实时同步软件之inotify
    一、rsync基础原理
    Samba实战
    DHCP企业实战
    NTP服务器企业实战
    Vsftpd服务器原理及部署
    Python的五大数据类型的作用、定义方式、使用方法,两种交互式方式,格式化输出的三种方式练习。
    pycharm快捷键,变量,字符串,类型的操作方法
    python基础归纳练习 python两种方式,垃圾回收机制,小数整池,数字类型,字符串类型。
  • 原文地址:https://www.cnblogs.com/sjsjsj-minus-Si/p/11634724.html
Copyright © 2020-2023  润新知