• 重写--全排列--全面理解搜索


    问题一:题意:输入一个整数n(n <= 9),输出1、2、3、······、n这n个数的全排列(按照字典序输出)。

    方法1:暴力写法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main(){
     5     int n=3, a[20];//以n=3为例,以此类推
     6     for(int i=0; i<n; i++)a[i]=i+1;//初始化序列
     7     
     8     for(int i=0; i<n; i++)
     9         for(int j=0; j<n; j++)
    10             if(i!=j)
    11                 for(int k=0; k<n; k++)
    12                     if(k!=i && k!=j)
    13                         //....//当n不等于3时以此类推 
    14                         cout<<a[i]<<" "<<a[j]<<" "<<a[k]<<endl; 
    15     return 0;
    16 }

    方法2:搜索写法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n, m;
     4 int a[100];
     5 bool vis[100];
     6 void dfs(int x)
     7 {
     8     if(x>n){
     9         for(int i=1; i<=n; i++)cout<<a[i]<<" ";
    10         cout<<endl;
    11         return;
    12     }
    13     for(int i=1; i<=n; i++)
    14     {
    15         if(!vis[i])
    16         {
    17             a[x]=i;
    18             vis[i]=1;
    19             dfs(x+1);
    20             vis[i]=0;
    21         }
    22     }
    23     
    24 }
    25 int main()
    26 {
    27     cin>>n;
    28     dfs(1);
    29     return 0;
    30  }

    方法3:递归写法

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n, a[10];
     4 
     5 void perm(int begin, int end){
     6     if(begin==end){
     7         for(int i=0; i<=end; i++)
     8             cout<<a[i]<<" ";
     9             cout<<endl;
    10     }
    11     else{
    12         for(int i=begin; i<=end; i++){
    13             swap(a[begin],a[i]);//把当前第一个数与后面的所有数交换位置 
    14             perm(begin+1,end);
    15             swap(a[begin],a[i]);//恢复,用于下次交换 
    16         }
    17     }
    18 }
    19 
    20 int main(){
    21     cin>>n;
    22     for(int i=0; i<n; i++)a[i]=i+1;//初始化数组值
    23     
    24     perm(0,n-1);//perm是permutation简写 
    25     return 0;
    26 }

    方法4:STL输出全排列

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 
     4 int main(){
     5     int n, a[20];
     6     cin>>n;//n小于20 
     7     for(int i=0; i<n; i++)a[i]=i+1;
     8     do{
     9         for(int i=0; i<n; i++)
    10             cout<<a[i]<<" ";
    11         cout<<endl;
    12     }while(next_permutation(a,a+n));//next_permutation注意拼写要牢记 
    13     
    14     return 0;
    15 }

    问题二:打印n个数中任意m个数的全排列;

        将问题一中方法2、方法3、方法4更改参数即可

    问题三:

    从1-m中选出n个数,要求同样的数字不能重复选择,按照字典序正序输出所有方案。
    
    例如:从1到4中选出2个数,共有6种方法,按照字典序输出,依次为:
    
    1 2
    1 3
    1 4
    2 3
    2 4
    3 4

     方法1:更改问题一》方法2》两种更改方法》自行脑补

     方法2:递归写法,理解了你就是大佬

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n, m;
     4 int a[20];
     5 void dfs(int cur, int sel){//cur填数,sel位数 
     6     if(sel==n){
     7         for(int i=0; i<n; i++)
     8             cout<<a[i]<<" ";
     9         cout<<endl;
    10         return;
    11     }
    12     for(int i=cur; i<=m; i++){
    13         a[sel]=i;
    14         dfs(i+1,sel+1);
    15     }
    16 }
    17 int main()
    18 {
    19     cin>>m>>n;
    20     dfs(1,0);
    21     
    22     return 0;
    23  } 

    问题四:打印n个数中任意m个数的组合(子集问题)

     step1:1~n的所有子集(难度较大,从二进制的角度考虑

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[10];
     4 void print_subset(int n)
     5 {
     6     for(int i=0; i<(1<<n); i++){
     7         for(int j=0; j<n; j++)
     8             if(i&(1<<j))
     9                 cout<<a[j]<<" ";
    10         cout<<endl;
    11     }
    12 }
    13 int main()
    14 {
    15     int n;
    16     cin>>n;
    17     for(int i=0; i<n; i++)a[i]=i+1;//初始化数组 
    18     print_subset(n);
    19     return 0;
    20  } 

     step2:打印1~n个数中任意m个数的组合(和问题二的解法比较)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int a[10];
     4 void print_subset(int n, int m)
     5 {
     6     for(int i=0; i<(1<<n); i++){
     7         int num=0, kk=i;//num统计i中1的个数;kk用来处理i
     8         while(kk){
     9             kk=kk&(kk-1);//清除kk中的最后一个1 
    10             num++;//统计1的个数 
    11         } 
    12         if(num==m){//二进制数中的1有k个,符合条件 
    13             for(int j=0; j<n; j++)
    14                 if(i&(1<<j))
    15                     cout<<a[j]<<" ";
    16             cout<<endl;
    17         }
    18     }
    19 }
    20 int main()
    21 {
    22     int n, m;
    23     cin>>n>>m;
    24     for(int i=0; i<n; i++)a[i]=i+1;//初始化数组 
    25     print_subset(n, m);
    26     return 0;
    27  } 
  • 相关阅读:
    objectivec 中 category 和 extension 的区别
    提高audioqueue启动时间的一个技巧
    iOS中url中文编码问题
    XP重装后grub引导修复( Ubuntu10.10 与XP双系统 )
    Ubuntu10.10 与XP双系统安装
    BSF脚本引擎
    随机访问类RandomAccessFile多线程下载
    Spring AOP解决系统日志备忘
    OA和KM知识管理的区别
    JavaMail接收指定账号邮件
  • 原文地址:https://www.cnblogs.com/tflsnoi/p/11946748.html
Copyright © 2020-2023  润新知