题目描述
给定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中唯一的元素;
当n>1时,perm®由(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 a[6];
int n;
void swap(char *a,char *b)
{
char t;
t=*a;
*a=*b;
*b=t;
}
int dfs(int t)
{
int i;
if(t==n-1)
{
for(i=0; i<n-1; i++)
printf("%c",a[i]);
printf("%c\n",a[i]);
return 0;
}
else
{
for(i=t; i<n; i++)//像回溯,却不是。
{
swap(&a[i],&a[t]);
dfs(t+1);
swap(&a[t],&a[i]);
}
}
}
int main()
{
int k,i,j,t;
char s;
while(~scanf("%d",&k))
{
n=0;
for(i=0; i<6; i++)
a[i]='\0';
while(k--)
{
scanf("%d",&n);
{
scanf("%c",&s);
for(i=0; i<n; i++)
{
scanf("%c%c",&a[i],&s);
}
/* printf("a数组值\n");
for(i=0;i<n;i++)
printf("%c",a[i]);
printf("\n");*/
dfs(0);
printf("\n");
}
}
}
}