题目描述
给定n个字符{r1,r2,…,rn},要求生成这n个字符的全排序。
生成全排列思想如下:
设R={r1,r2,…,rn}是要进行排列的n个元素,Ri=R-{ri}。
集合X中元素的全排列记为perm(X)。
(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列。R的全排列可归纳定义如下:
当n=1时,perm(R)=(r),其中r是集合R中唯一的元素;
当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),…,(rn)perm(Rn)构成。
输入
输入包括若干个用例,第一行为一个正整数k(1<=k<=10),表示用例个数。
每个用例占两行,其中第一行为该用例字符的个数n(1<=n<=5),第二行为n个字符,字符可以是数字和大小写字母,字符之间用空格隔开。
可以假定给定同一用例中不出现相同的字符。
输出
输出每个用例的全排列,每一个排列占一行。各用例全排序之间用一空行隔开。
样例输入 复制
2 2 1 2 3 a c b
样例输出 复制
12 21 acb abc cab cba bca bac
- 刚开始是想按顺序从每一个开始,穷举的,但是发现答案对是对了但是不一致。
- 这个是交换然后递归,递归回来又像回溯。
- 它也是要自己和自己交换的,不然会缺少情况(后面全排列)。
- 它是首先把所有后面的和自己的位置交换(因为它总是从第一个开始,所以不用担心会列举不完),换的同时往下递归,是确定这个位置是它(和它后面的字符)情况接下来的全排列。回来的时候要交换回来不能改变原先的数组。
-
#include<stdio.h> char b[6]={0},re[6]={0}; int slove(char a[],int pos,int n)//当前坐标总是和第一个交换输出 { int i,j; char t; if(pos==n-1) { printf("%s\n",a); return 0; } for(i=pos;i<n;i++) { t=a[i];a[i]=a[pos];a[pos]=t; slove(a,pos+1,n); t=a[i];a[i]=a[pos];a[pos]=t; } } int main() { int k,i,j,n; char s[11][5]={0},b[5]={0}; scanf("%d\n",&k); for(i=0;i<k;i++) { scanf("%d\n",&n); for(j=0;j<n;j++) { scanf("%c",&s[i][j]); getchar(); } slove(s[i],0,n); printf("\n"); } return 0; }