重寫--全排列--全面理解搜索


問題一:題意:輸入一個整數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  } 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM