深度优先搜索就好比走迷宫, 不断顺着一条路走, 直到走不通为止,
然后回退到上一个路口再向另外的方向行走(走过的方向就不会再走了,又不是傻子, 知道走不通,还向走不通的方向走), 不断重复(试过所有路口,
状态转移), 重复直到找到唯一的一条合适的路径; DFS可以看做是二叉树的先序遍历。

  • 问题引入

引入问题:输入一个数n,输出1~n的全排列。
在这里我们将问题形象化,举个例子,假如有编号为1,2,3的3张扑克牌和编号为1,2,3的3个盒子。现在需要将这3张扑克牌分别放到3个盒子里面,并且每个盒子有且只能放一张扑克牌。那么一共有多少种不同的放法呢?

  • 逐步深入

现在要生成的是全排列,约定一个顺序,每次到一个盒子面前,都先放1号,再放2号,最后放3号扑克牌。
开始,把1号扑克放进1号盒子,把2号扑克放进2号盒子,最后把3号扑克放进3号盒子,现在已经形成了一种排列,这个排列就是前面盒子中的扑克牌的号码,即“1,2,3”。
产生了一种排列之后,需要立即返回。
现在小哼 需要退一步回到3号盒子面前,需要取回之前放在3号盒子中的扑克牌,再去尝试看看还能否放别的扑克牌,从而产生一个新的排列。
于是小哼取回了3号扑克牌,当小哼再想往3号盒子放别的扑克的时候,发现手中仍然只有3号扑克牌,没有别的选择。于是小哼不得不再往后会退一步,回到2号盒子面前。
小哼回到2号盒子后,收回了2号扑克牌。现在小哼手里面有两张扑克牌了,分别是2号和3号扑克牌。按照之前约定的顺序,现在需要往2号盒子中放3号扑克牌(上一次放的是2号扑克牌)。放好之后小哼又向后走了一步,再次来到3号盒子面前。
小哼再次来到3号盒子后,将手中仅剩的2号扑克牌放入了3号盒子。此时又产生了一个新排列“1,3,2”
按照刚才?️ 步骤去模拟,便会依次生成所有排列:“2 1 3”,“2 3 1”,“3 1 2”,“3 2 1 ”。

  • 如何用程序实现呢?

说了这么半天,这么复杂的过程应该如何用程序实现呢?
我们现在来解决最基本的问题:如何往小盒子中放扑克牌。每个小盒子都可能放1号,2号,3号扑克牌,需要一一尝试,这里一个for循环就能解决。

这里数组a是用来表示小盒子的,变量step表示当前正处在第step个盒子面前。a[step]=i;就是将第i号扑克牌放入第step个盒子中。这里还有一个问题就是,如果一张扑克牌已经放到别的盒子中了,那么此时就不能再放入同样的扑克牌到当前的小盒子中,因为此时手中已经没有这张扑克牌了。因此还需要一个数组book来标记哪些牌已经使用了。

for (i=1;i<=n;i++){if (book[i]==0){a[step]=i;book[i]=1;}}
  • 如何处理第step+1个小盒子?

ok,现在已经处理完了第step个小盒子了,接下来需要往下走下一步,继续处理第step个小盒子。那么如何处理第step+1个小盒子呢?处理方法其实和我们刚刚处理第step个盒子的方法是相同的。因此很容易想到把刚才处理第step个小盒子的代码封装成一个函数,给这个函数起名为dfs。

写成函数之后,刚才的问题就很好解决了。在处理完第step个盒子之后,紧跟着处理第step+1个小盒子,处理第step+1 个小盒子的方法就是dfs(step+1).

dfs(step+1);
book[i]=0;

上面代码的 book[i]=0 这条语句非常重要,这句话的作用是将小盒子中的扑克牌收回,因为在一次摆放尝试返回的时候,如果不把刚才放入小盒中的扑克牌收回,那将无法进行下一次摆放。

还有一个问题,就是什么时候输出一个满足要求的序列呢?
其实当我们处理到第n+1个小盒子的时候,即step = n+1 ,那么说明前n个盒子都已经放好扑克牌了,这里就将1~n个小盒子中的扑克牌编号打印出来就可以了。⚠️ 注意,打印完毕一定要return,不然这个程序就会永无止境的运行下去 。

  • 完整的代码如下:
#include <stdio.h>
int a[10],book[10],n;void dfs(int step)
{int i;if(step==n+1){for (i=1;i<=n;i++)printf("%d ",a[i]);printf("\n");return;}for (i=1;i<=n;i++){if (book[i]==0)   //book[i]等于0表示i号扑克牌仍然在手上{a[step]=i;    //将i号扑克牌放入到第step个盒子中book[i]=1;    //将book[i]置为1,表示i号扑克牌已经不在手上dfs(step+1);book[i]=0;}}return;
}int main()
{scanf("%d",&n);dfs(1);getchar();getchar();return 0;
}
  • 深度优先搜索的基本模型
    理解深度优先搜索 的关键在于解决“当下该如何做”。至于“下一步如何做”,则与“当下如何做”是一样的。比如这里我们写的dfs(step)函数的主要功能就是解决第step个盒子的时候你该怎么办。通常的方法就是把每一种可能都去尝试一遍(一般使用for循环来遍历)。当前这一步解决后方便进入下一步dfs(step+1)。下一步解决方法和当前这步的解决方法是完全一样的。
    下面的代码是深度优先搜索的基本模型。
void dfs(int step)
{判断边界尝试每一种可能  for(i=1;i<n;i++){继续下一步  dfs(step+1);}返回
}

每一种尝试就是一种“拓展”。每次站在一个盒子面前的时候,其实都有n中拓展方法,但是并不是每种拓展都能够拓展成功。

引用博文链接:https://blog.csdn.net/qq_40845344/article/details/82874580

以上内容均来自于人民邮电出版社出版的啊哈!算法!!!!!作者纪磊,有需要的可以直接购入图书,以上是本人的学习笔记。

深度优先搜索--不撞南墙不回头相关推荐

  1. “ 一条路走到黑,不撞南墙不回头”——C++【DFS(深度优先搜索算法)】入门讲解

    Hello,大家好,我是Amy,好久不见(我真好意思说好久不见)~ 虽迟但到,你们一直催更的dfs算法终于来啦~ 话不多说,让我们直接进入主题吧! 目录 缺点 简介 "地图类" 深 ...

  2. 算法简介:不撞南墙不回头----深度优先搜索算法(DFS)

    算法简介:不撞南墙不回头----深度优先搜索算法(DFS) 算法简介 算法简介 DFS算法简介 略 DFS算法思想 首先以一个未被访问过的顶点作为起始顶点,沿当前顶点的边走到未访问过的顶点;当没有未访 ...

  3. 【DFS】不撞南墙不回头—深度优先搜索算法[Deep First Search]

    今天上午听到,那个非常6+1的李咏先生因癌症去世 DFS算法的基本模型 深度下,不撞南墙不回头,就是一直往后找,知道没有路了,向后返回. 想起一首民谣,<可能否>--木小雅 https:/ ...

  4. 深度优先算法(一路走到底,不撞南墙不回头)

    一条路走到底,不撞南墙不回头,深度优先算法就是一个这样的'莽夫',然而就是一位这样的'莽夫',却是我们刷算法题的一个必不可少的制胜法宝. 深度优先算法特点: 只要前面有可以走的路,那就一直往前走,直到 ...

  5. c++ 不撞南墙不回头——树形动态规划(树规)

    不撞南墙不回头--树规总结                                         焦作一中信息学oy 之所以这样命名树规,是因为树规的这一特殊性:没有环,dfs是不会重复,而 ...

  6. 转不撞南墙不回头——树规总结

    之所以这样命名树规,是因为树规的这一特殊性:没有环,dfs是不会重复,而且具有明显而又严格的层数关系.利用这一特性,我们可以很清晰地根据题目写出一个在树(型结构)上的记忆化搜索的程序.而深搜的特点,就 ...

  7. 不撞南墙不回头——树形动态规划(树规)

    不撞南墙不回头--树规总结                                         焦作一中信息学oy 之所以这样命名树规,是因为树规的这一特殊性:没有环,dfs是不会重复,而 ...

  8. 所谓的不撞南墙不回头

    只愿自己一派纯真,不撞南墙不回头 -- 挣扎在计算机领域的小萌新 (1) 回顾你过去三年的学习经历 ♥ 当初你报考的时候,是真正喜欢计算机这个专业么? 答: 报考啊...怎么说呢,我从高中的时候就已经 ...

  9. Scratch教学课程:不撞南墙不回头

    Hi,大家好,本次介绍Scratch的基础运用,内容如下: 使用角色制作动画并在舞台上移动 理解Scratch基本的运动.外观.条件控制等基础积木的应用. 响当当老师把本次的项目叫做:不撞南墙不回头. ...

最新文章

  1. 因一个计算机故障而“停工”!观测宇宙 30 多年的哈勃太空望远镜还能坚持多久?...
  2. javabirdge php_PHP-Java-Bridge使用笔记,2014年9月最新版
  3. WINDOWS系统常用程序及快捷键
  4. Smalidea+IntelliJ IDEA/Android Studio动态调试安卓app教程
  5. android工程建立到最后一步提示unsupported template dependency的解决方法
  6. JAVA企业级应用TOMCAT实战视频课程
  7. 前端学习(511):两列布局的第一种方式
  8. 论文浅尝 - JWS2020 | FEEL: 实体抽取和链接的集成框架
  9. 同一个路由器下的不同网段如何实现ping通
  10. P2610 【[ZJOI2012]旅游】(dfs+树的直径)
  11. Atitit各种SDM 软件SDP sdm的ddd tdd bdd设计
  12. jsp实现简易购物车
  13. swf转换mp4 linux,转换FLA文件,以.swf文件在Linux上
  14. 快闪类企业校园招聘H5,这么设计才够炫!
  15. 推荐一些stm32和DSP的学习视频和教程(资料)
  16. 前端在登录时如何将用户密码加密
  17. jeecg中高级查询的写法
  18. CAN工具 - PCAN - 半自动化
  19. 比 B 站好用,堪称二次元福音!GitHub 这款「动漫搜番」神器我爱了!
  20. SVN :Cannot verify lock on path XXX,no username available

热门文章

  1. 病毒防治:清除***从它的寄生地开始
  2. 【图像分割】基于混洗Shuffled Complex Evolution实现图像分割附matlab代码
  3. hadoop安装作业
  4. python3 logging输出到文件_python3:logging模块 输出日志到文件
  5. C#调用RabbitMQ实现消息队列
  6. c++、7-5 估算数学常数e的值
  7. 阿里云服务器和虚拟主机之间的区别
  8. html给页面添加艺术型边框,如何为2016word的页面设置艺术型页面边框
  9. 【读书笔记 | 自动驾驶中的雷达信号处理(第4章 雷达波形及其数学模型)】
  10. 数据中心机房设备标签规范建议