排列数字----dfs的基础模版

 题目描述如下:

 

 dfs的本质实际上是递归,想要真正理解dfs的代码运行过程,对于刚接触的同学只看代码是很抽象的,这里强烈建议手动模拟一遍代码怎么运行123的全排列,同时不断思考每一步的意义是什么,如果没有这个操作会导致什么,回溯的过程具体是什么样的,达到了什么效果

这里用箱子里边放卡片作为比喻能更清晰的想象出运行过程,其中我们的path数组用来记录n个箱子中分别放了什么内容的卡片,也就是记录排列结果的数据;check数据来记录卡片是否还在你手中;u代表你当前站在哪个箱子面前。当你站在最后一个箱子前时,就找到了一种所有卡片放进箱子里(全排列)的情况,此时我们输出结果

而在第u个箱子面前我们的操作是:用i循环遍历0号卡到最后一张卡牌,依次检查还在不在自己手上,如果不在,用过了(check(i)==true),则不操作这张牌,for循环到下一张牌检查下一张牌是否在手里,若不在,继续找下下一张,直到所有牌都用过(i==n)为止,此时对应循环结束

如果第i张牌还在手里,我们则对其进行如下操作:将牌放到当前u号箱子里,并记录一下(path【u】=i),记录i号牌用掉了(check[i]=true),走到下一个箱子面前(dfs(u+1))

对于最后一行check【i】=false的回溯,我们理解为当u==n,我们走到头的时候,将卡牌i再拿回来,让后再走回上一个箱子面前(由函数递归,向上一层归完成我们向回走的过程),判断能否有其他放法

这里注意由于i是不会回退的,所以不会出现重复情况,即1号牌放入3号箱子后,拿回后i++(1号变2号卡),3号箱子就不会再去让1放进去了,而是将二放进去,这也是很多同学迷的一个点

如果以上说明还是似懂非懂,还是建议手动模拟代码,并反复思考着过程的同时亲手写一下代码

ac代码如下: 

#include <bits/stdc++.h>
using namespace std;
const int N=10;
int n;
int path[N];
bool check[N];
void dfs(int u){
    if(u==n){//当深度u等于数据要求n的时候,即达到树的最深处,盒子的最后一个面前
        for(int i=0;i<n;i++){
            cout<<path[i]<<" ";
        }
        cout<<endl;
        return;
    }
    for(int i=0;i<n;i++){
        if(check[i]==false){//当前卡片还没被用过
            check[i]=true;//放下卡牌到箱子里,该卡用过了
            path[u]=i+1;//记录第u个箱子中放入了值为i+1的卡牌
//(由于下标从零开始但是数据是从一开始,卡片内容和卡片索引差一)
            dfs(u+1);//走到下一个盒子面前继续如上判断
            check[i]=false;//关键回溯的一步,将卡牌从当前箱子中再拿出来
        }
    }
}
int main(){
    cin>>n;
    dfs(0);
    return 0;
}

题目来源: 

842. 排列数字 - AcWing题库

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值