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