1.题目
全排列问题
Time Limit: 10000 ms Memory Limit: 65536 KiB
Problem Description
从n个不同元素任取m(m<=n)个元素,按照一定的顺序排列起来,叫做从n个不同元素中取出m个元素的一个排列,当m=n时所有的排列情况叫全排列。现输入n个递增的数,请你输出这n个数的全排列。全排列输出顺序如样例所示。
Input
多组输入。
首先输入一个数据组数T(1<=T<=100)
接下来是T组数据。
每组数据有两行。
第一行先输入一个整数n(1<=n<=10)。
接下来是一行输入n个由空格分开的互不相同的整数num(1<=num<=90000)。
Output
对于每组数据,每一种排列占一行,各元素间用逗号隔开。
Sample Input
1
3
1 2 3
Sample Output
1,2,3
1,3,2
2,1,3
2,3,1
3,2,1
3,1,2
2.正确代码:
#include <iostream>
#include <stdio.h>
using namespace std;
int num[11];
void swap(int a,int b)
{
int t=num[a];
num[a]=num[b];
num[b]=t;
}
void AllRange(int k,int m)
{
int i;
if(k==m+1)
{
for(i=1;i<=m;i++)
{
if(i==m)
cout << num[i] <<endl;
else
cout << num[i] << ',';
}
}
else
{
for(i=k;i<=m;i++)
{
swap(i,k);
AllRange(k+1,m);
swap(k,i);
}
}
}
int main()
{
int m,n,i,T;
while(cin >> T)
{
while(T--)
{
cin >> n;
for(i=1;i<=n;i++)
cin >> num[i];
AllRange(1,n);
}
}
return 0;
}
3.代码解读
1.你应该明确代码在递归中的顺序,我们需要的是遍历所有的情况,当到达最低端的再往下一端时,就说明递归完成,然后就进行输出了。
2.我们现在先思考如何全部便利呢?答案,在递归中使用For循环来实现遍历全部的元素。
5~4~3~2~1
这样类似可能的情况,当开始的时候,这时的选择的可能性最大,有5种,而之后进入第二层就有四种,这样依次往下递减,对于这种操作,我们用下面这种代码格式:
void func(int i,k)
{
for(j=i;j<=k;j++)
{
````
func(i+1,k);
````
}
}
这时实现全排列的基础,这个概念一定要明确,即遍历这里面全部的可能。
3.现在,我们有了基础,再往上考虑,我们如何实现互换呢?我们是想要实现有所保留,即我们往里之后,当退回来之后,能恢复到进去之前原来的样子,这样,我们就可以来实现稳步改变。
注意,机器的设计思想是要高度的具有可重复性,我们应该设计一种具有高度重复的算法。
我们 改变-进去-恢复-值改变(保证不会重复改变),这种方法可以让我们避免重复的改变。
这里的核心算法:
for(i=k;i<=m;i++)
{
swap(i,k);
AllRange(k+1,m);
swap(k,i);
}
只能在k后面的进行交换,我们的层数越高,那么当前该层的值交换就越优先,进位进去时,k++,这样,在下面那层,无法对该层造成影响,知道最后,这样就能进行关于你全排列的要求了。