生成可重集的排列(方法)
通过暴力或者dfs的方法可以很容易地得到n个数的全排列,可生成可重集的呢,例如给出一个数组a[],要求输出这个数组的全排列,与普通的求全排列不同,数组中很可能存在重复的数,所以方法都需要改一改:
DFS
#include"iostream" #include"cstring" #include"cstdio" using namespace std; int n,book[21],a[21]; int ca=1; void dfs(int step) { if ((step == n)) { for(int i=1; i<n; i++) cout<<a[i]<<' '; cout<<a[n]<<endl; return; } for(int i=1; i<=n; i++) if(book[i]<=2) //这里表示重复的数最多可以有两个 { a[step+1]=i; book[i]++; dfs(step+1); book[i]--; } } int main() { int x=1; while(scanf("%d",&n)!=EOF) { //a[1]=1; if(x>1) cout<<endl; x++; cout<<"Case "<<ca++<<':'<<endl; dfs(0); } return 0; }
暴力:
#include"iostream" #include"cstring" #include"cstdio" using namespace std; int n,book[21],a[21]; int ca=1; void print(int step) { if ((step == n+1)) { for(int i=1; i<n; i++) cout<<a[i]<<' '; cout<<a[n]<<endl; } for(int i=1; i<=n; i++) { int ok=1; for(int j=2; j<step; j++) //这里j=2表示最多可以有2个重复的数 if(a[j]==i) ok=0; if(ok) { a[step]=i; print(step+1); } } } int main() { int x=1; while(scanf("%d",&n)!=EOF) { memset(a,0,sizeof(a)); if(x>1) cout<<endl; x++; cout<<"Case "<<ca++<<':'<<endl; print(1); } return 0; }
最后还有一个STL的函数,更简洁好用
#include"iostream" #include"algorithm" using namespace std; int main() { int n,p[10]; while(cin>>n) { for(int i=0; i<n; i++) cin>>p[i]; sort(p,p+n); do { for(int i=0; i<n; i++) cout<<p[i]<<' '; cout<<endl; } while(next_permutation(p,p+n)); } return 0; }