C: 全排列问题
描述
生成一个1..N的全排列.
输入
第一行包括一个数字 n 小于 9
输出
按字典序输出1...N的所有全排列.
样例
输入: 3
输出: 123 132 213 231 312 321(a,b,c)
状态转移方程为: A(n, n)=A(n,1)(组合+)A(n-1,1)....A(1,1)
实现全排列和组合不一样的地方在于,对于(a,b,c)——(a,b)的遍历 不需要设置 a (表头)的上限,
只需要要求已经置入的数不再重复即可——因为组合可以用上界来限制,而这个表达比较困难,所以用bool数组标记来表示
代码如下,固定第一个数
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 typedef long long ll; 9 using namespace std; 10 int n; 11 int a[11]; 12 bool x[11]; 13 void f(int it,int num) { 14 //num表示此时已经排列了几层(栈的深度) 15 //it表示下一个要压入的数 16 a[num]=it;//入栈 17 x[it]=1;//mark 18 if(num==n) { 19 for(int j=1; j<=n; j++) { 20 cout<<a[j]<<" "; 21 } 22 printf(" "); 23 } else { 24 for(int i=1; i<=n; i++) { 25 if(x[i]==1)continue; 26 else f(i,num+1); 27 } 28 } 29 x[it]=0; 30 } 31 32 int main () { 33 cin>>n; 34 memset(x,0,sizeof(x)); 35 for(int i=1; i<=n; i++) { 36 f(i,1); 37 } 38 39 return 0; 40 }
从0位开始
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 typedef long long ll; 9 using namespace std; 10 int n; 11 int a[11]; 12 bool x[11]; 13 void f(int it,int num) { 14 //num表示此时已经排列了几层(栈的深度) 15 //it表示下一个要压入的数 16 a[num]=it;//入栈 17 x[it]=1;//mark 18 if(num==n) { 19 for(int j=1; j<=n; j++) { 20 cout<<a[j]<<" "; 21 } 22 printf(" "); 23 } else { 24 for(int i=1; i<=n; i++) { 25 if(x[i]==1)continue; 26 else f(i,num+1); 27 } 28 } 29 x[it]=0; 30 } 31 32 int main () { 33 cin>>n; 34 memset(x,0,sizeof(x)); 35 36 f(0,0); 37 38 39 return 0; 40 }
改写成组合数,就是利用 1234 123 124 134, 每次后面一位都比前面大因此,此时不再从1开始,而是从上一个it+1开始找
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 typedef long long ll; 9 using namespace std; 10 int n; 11 int r; 12 int a[11]; 13 bool x[11]; 14 void f(int it,int num) { 15 //num表示此时已经排列了几层(栈的深度) 16 //it表示下一个要压入的数 17 a[num]=it;//入栈 18 x[it]=1;//mark 19 if(num==r) { 20 for(int j=1; j<=r; j++) { 21 cout<<a[j]<<" "; 22 } 23 printf(" "); 24 } else { 25 for(int i=it+1; i<=n; i++) { 26 if(x[i]==1)continue; 27 else f(i,num+1); 28 } 29 } 30 x[it]=0; 31 } 32 33 int main () { 34 cin>>n>>r; 35 memset(x,0,sizeof(x)); 36 for(int i=1; i<=n-r+1; i++) { 37 f(i,1); 38 } 39 40 return 0; 41 }
进一步简化
1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cstdio> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 typedef long long ll; 9 using namespace std; 10 int n; 11 int r; 12 int a[11]; 13 bool x[11]; 14 void f(int it,int num) { 15 //num表示此时已经排列了几层(栈的深度) 16 //it表示下一个要压入的数 17 a[num]=it;//入栈 18 x[it]=1;//mark 19 if(num==r) { 20 for(int j=1; j<=r; j++) { 21 cout<<a[j]<<" "; 22 } 23 printf(" "); 24 } else { 25 for(int i=it+1; i<=n; i++) { 26 if(x[i]==1)continue; 27 else f(i,num+1); 28 } 29 } 30 x[it]=0; 31 } 32 33 int main () { 34 cin>>n>>r; 35 memset(x,0,sizeof(x)); 36 37 f(0,0); 38 39 40 return 0; 41 }