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;
            }
        }
    }
}
posted @ 2025-08-24 09:24  hardestnut  阅读(26)  评论(0)    收藏  举报