题意:顾名思义,就是输入若干次数字,将1到该数字的全排列输出
算法:DFS
问题:第一次接触DFS算法问题,并不容易理解其中递归的写法(特别是回溯的理解)。具体问题可见代码注释部分。(有一次写了dfs(++step)就错了,因为每层之内的step不能轻易改变,后面回溯回来也是需要查看step值的,只能用step+1)
思路:每选择一个数后,将该数标记,将未标记过的的数看作一个小的全排列问题,依次转化,转化n-1次后结束,输出该次排列。再将最后一次小的全排列问题用到的数字的标记取消,就可以退回到第n-2次转化后的结果,再往下进行新的全排列,每层结束都会回溯到上一层。(难点:vis[i]=0就是这个作用,通过让标记取消回溯)
代码:ac
#include<bits/stdc++.h>
using namespace std;
int n;
int num[10], vis[10];/*前者存放选中的数,后者存放该数字是否选中的标记*/
void dfs(int step);
int main()
{
while (scanf("%d", &n) == 1)
{
memset(vis, 0, sizeof(vis));
dfs(1);
}
return 0;
}
void dfs(int step)
{
if (step == n + 1)/*先写出口*/
{
for (int i = 1; i <= n; i++)
{
printf("%d ", num[i]);/*输出该次排列选中的数*/
}
printf("\n");
return;
}
for (int i = 1; i <= n; i++)
{
if (vis[i] == 0)
{
num[step] = i;/*存放排列选中的数字*/
vis[i] = 1;/*标记该数字已选过*/
dfs(step + 1);/*进行该排列的下一步,选择下一个未选过的数字*/
vis[i] = 0;/*如果不写这个,一次排列就结束了,无法回溯;写了以后,可以回到上一层的下一个i + 1继续排列*/
}
}
}