深度优先搜索(DFS)
1.关于搜索
严格来说,搜索算法也是一种暴力枚举策略,但是其算法特性决定了效率比直接枚举所有答案要高,因为搜索可以跳过一些无效状态,降低问题规模。有些题目,无法用简单的循环表示所有枚举情况,需要寻找更加一般化的枚举框架;有些题目,本质上是子集枚举或是排列枚举,但是枚举量过大,需要剪掉过多的无效状态—深度优先搜索应运而生。
2.什么是深度优先搜索?
DFS 全称 Depth First Search,中文名是深度优先搜索,是一种用于遍历或搜索树或图的算法.沿着树的深度遍历树的节点,尽可能深的搜索树的分支。当节点v的所在边都己被探寻过,搜索将回溯到发现节点v的那条边的起始节点。这一过程一直进行到已发现从源节点可达的所有节点为止。
如果还存在未被发现的节点,则选择其中一个作为源节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。属于盲目搜索。简单来说就是一条路走到黑,直到没路了,或者找到结果才返回。
深度优先搜索算法的基础:递归与回溯
递归与回溯是相辅相成的,有递归就会有回溯,递归函数的下面部分就是回溯的过程以及回溯的逻辑(即递归是回溯的基础)
3.如何理解
回溯算法可以抽象为一个树状结构,可以抽象为一个n叉树问题。如果满足递归条件,则继续搜索,直到满足题目要求。如果走到尽头还未满足则回溯。
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
|
图例如下:
我们若以1为出发点开始遍历,那么我们其中一条搜索的遍历顺序则为1->2->4->7->4->8->4->2->1,遍历过程中我们要做的就是不断地向下向深处去搜索,秉承着不撞南墙不回头的思想,一直遍历到最下方,直到无法遍历,那我们向上回溯到它的父亲节点,向它的另一个子节点继续搜索。不断重复上述操作。
我们从1号点出发选择左节点,紧接着向下搜索到达4号点,4号点同样有两种选择,先搜索左节点到达7号点,发现无路可走,向上回溯到达4号点,搜索右节点到达8号点后发现同样无路可走,接着向上回溯到达4号点,再次向上回溯到达2号点再到1号点。紧接着搜索1号点的右节点,将所有点搜素完毕后,以1号点为出发点的一次遍历才算结束。
栈实现
DFS 可以使用 栈(Stack) 为遍历中节点的暂存容器来实现;这与用 队列(Queue) 实现的 BFS 形成高度对应。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
|
4.例题解析
一道经典例题:LuoguP1605 迷宫(普及-)(给大家直接抓取了,大家也可以去洛谷自行查看)
题目链接:https://www.luogu.com.cn/problem/P1605
题目描述
给定一个 \(N \times M\) 方格的迷宫,迷宫里有 \(T\) 处障碍,障碍处不可通过。
在迷宫中移动有上下左右四种方式,每次只能移动一个方格。数据保证起点上没有障碍。
给定起点坐标和终点坐标,每个方格最多经过一次,问有多少种从起点坐标到终点坐标的方案。
输入格式
第一行为三个正整数 \(N,M,T\),分别表示迷宫的长宽和障碍总数。
第二行为四个正整数 \(SX,SY,FX,FY\),\(SX,SY\) 代表起点坐标,\(FX,FY\) 代表终点坐标。
接下来 \(T\) 行,每行两个正整数,表示障碍点的坐标。
输出格式
输出从起点坐标到终点坐标的方案总数。
样例 #1
样例输入 #1
1 2 3 |
|
样例输出 #1
1 |
|
提示
对于 \(100\%\) 的数据,\(1 \le N,M \le 5\),\(1 \le T \le 10\),\(1 \le SX,FX \le n\),\(1 \le SY,FY \le m\)。
这是洛谷上一道基础的dfs入门题,可以通过这道题来了解一下dfs,练练手。
AC码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
|
dfs的整体思路还是比较容易想的,大家在写的过程中只需要将判断条件以及边界处理好即可
5.精选好题推荐(难度升序排列)
3.P1219 [USACO1.5] 八皇后 Checker Challenge(普及/提高-)
4.P2052 [NOI2011] 道路修建(普及/提高-)
5.P3956 [NOIP2017 普及组] 棋盘(普及+/提高)
6.P3659 [USACO17FEB] Why Did the Cow Cross the Road I G(提高+/省选)
PS:再高难度的题的话就不只是针对于dfs来考的了,所以这里不再给出,当然感兴趣同学可以自己上洛谷或者acwing查看
by LosTcrab