题目描述:
按照字典序输出自然数 11 到 n 所有不重复的排列,即 n 的全排列,要求所产生的任一数字序列中不允许出现重复的数字。
输入格式:
一个整数 n。
输出格式:
由 1∼n 组成的所有不重复的数字序列,每行一个序列。
每个数字保留 5个场宽。
输入输出样例:
输入:3
输出: 1 2 3
1 3 2
2 1 3
2 3 1
3 1 2
3 2 1
思路:
这题是一道用dfs解决的经典问题。
我们可以这样想,有n个数,那么就会有n个空位要填进去数。
那么终止条件就应该是当已经填的空位数等于n时。
在dfs中,从1到n循环依次判断能否放入空位中。
1:若能,将此数存放置数组内并递归下一个空位,也就是dfs(x+1)。
2:若不能,则接着判断下一个数。
而此处的判断条件应该是此数是否出现过,因为全排列不能出现相同的数。
我们可以定一个vis[]数组来判断此数是否出现过(开始全部为false)。
判断时,只需看看这个位置的数组元素是true还是false。
如果是真执行‘思路’正数第四行,如果是假执行‘思路’正数第五行。
最后一定要记得把vis[]设为false(也就是回溯)!
参考代码:
#include<bits/stdc++.h>
using namespace std;
bool vis[10];
int n,a[100];
void dfs(int k)
{
//当已经填好的空位数=n时,按格式输出a[i]并终止
if(k==n)
{
for(int i=1;i<=n;i++) cout<<setw(5)<<a[i];
cout<<endl;
return;
}
//判断 + 填数
for(int j=1;j<=n;j++)
{
if(!vis[j])
{
a[k+1]=j;
vis[j]=true;//不能再用这个数了
dfs(k+1);//这个位置已经填好,递归填下一个
vis[j]=false;//回溯
}
}
}
int main()
{
cin>>n;
dfs(0);//表示已经填好的空位数
return 0;
}
我还是一名小学生,代码可能有点繁琐,希望大家多多支持,谢谢。