1、生成1~n的排列
#include<stdio.h> #include<string.h> const int N=1e3+10; int a[N]; void print_permutation(int n,int *a,int cur) { int i,j; if(cur==n) /*递归边界*/ { for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); } else { for(i=1;i<=n;i++) /*尝试在a[cur]中填各种整数i*/ { int ok=1; for(j=0;j<cur;j++) if(a[j]==i) /*如果i已经在a[0]~a[cur-1]出现过,则不能再选*/ { ok=0; break; } if(ok) { a[cur]=i; print_permutation(n,a,cur+1); /*递归调用*/ } } } } int main() { int n; while(~scanf("%d",&n)) print_permutation(n,a,0); return 0; }
2、生成可重集的排列
上面求排列的程序只适用于任意两个元素均不相同的序列,如果要求有元素相同的序列的排列时,则需要对上面的程序进行修改。
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int N=1e3+10; int a[N],p[N]; void print_permutation(int n,int *p,int *a,int cur) { int i,j; if(cur==n) { for(i=0;i<n;i++) printf("%d ",a[i]); printf("\n"); } else { for(i=0;i<n;i++) if(p[i]!=p[i-1]) { int c1=0,c2=0; for(j=0;j<cur;j++) if(a[j]==p[i]) c1++; for(j=0;j<n;j++) if(p[i]==p[j]) c2++; if(c1<c2) { a[cur]=p[i]; print_permutation(n,p,a,cur+1); } } } } int main() { int n,i; while(~scanf("%d",&n)) { for(i=0;i<n;i++) scanf("%d",&p[i]); sort(p,p+n); print_permutation(n,p,a,0); } return 0; }
3、求下一个排列
枚举所有排列的另一个方法是从字典序最小的排列开始,不停调用“求下一个排列”的过程。 如何求下一个排列呢?C++的STL中提供了一个库函数next_permutation。
#include<stdio.h> #include<algorithm> using namespace std; int main() { int n,i,p[10]; while(~scanf("%d",&n)) { for(i=0;i<n;i++) scanf("%d",&p[i]); sort(p,p+n); /*排序,得到p的最小排列*/ do { for(i=0;i<n;i++) printf("%d ",p[i]); /*输出排列p*/ printf("\n"); }while(next_permutation(p,p+n)); /*求下一个排列*/ } return 0; }