u534714 排列数字题解(dfs)
题目描述
给定一个整数 n,将数字 1∼n 排成一排,将会有很多种排列方法。
现在,请你按照字典序将所有的排列方法输出
输入格式
共一行,包含一个整数 n
输出格式
按字典序输出所有排列方案,每个方案占一行
思路
如果我们每次确定一个数,那么下一个数就是从除了这个数以外的数里面选取,下下个同理,这种排列过程很像树。
于是考虑用dfs遍历这棵树,每次到底就输出,没到底就递归下一层(注意是层,每层可能的数和除开祖宗节点的数以外,剩余的数是一样的,遍历一层才会走完),再马上清空遍历数据。
代码如下:定义if_get,若是if_get[i]为零说明没用过。path[i]储存我们走的这条路的数据
关于dfs函数,如果u为n就输出所有数,反之的话,我们找到所有没被用的数,这些数就是所有子树,并储存在path里面,再递归所有子树(对应这里for循环),最后再还原if_get和path,避免影响后面的递归。
这里关键是想明白递归的位置和为什么递归可行。我们注意到一个递归在递归到底之前都不会触发if_get和path的还原,而这两个都会正确的输出本次递归。当到底之后return,到了倒数第二层,最后一层的if_get和path被重置,接着触发for循环的递归右子树,又会到右子树最底层,输出完事后开始倒数第三层的递归。发现整个过程就是标准的dfs。清空操作就是要放到递归操作后面,这样能使得只清空完成递归return的那几层。
代码
#include<iostream>
using namespace std;
void dfs(int u);
int n;
const int maxn=100;
int path[maxn];
bool if_get[maxn]={false};
int main(){
cin>>n;
dfs(0);
}
void dfs(int u){
if(u==n){
for(int i=0;i<u;i++){
cout<<path[i]<<" ";
}
cout<<endl;
return ;
}
else{
int i;
for(i=1;i<=n;i++){
if(!if_get[i]){
path[u]=i;
if_get[i]=true;
dfs(u+1);
path[u]=0;
if_get[i]=false;
}
}
}
}

浙公网安备 33010602011771号