广度优先搜索(BFS)
1.什么是广度优先搜索
百度对它的定义是这样的:宽度优先搜索算法(又称广度优先搜索)是最简便的图的搜索算法之一,这一算法也是很多重要的图的算法的原型。Dijkstra单源最短路径算法和Prim最小生成树算法都采用了和宽度优先搜索类似的思想。其别名又叫BFS,属于一种盲目搜寻法,目的是系统地展开并检查图中的所有节点,以找寻结果。换句话说,它并不考虑结果的可能位置,彻底地搜索整张图,直到找到结果为止。
我们给出进一步的解释:它是从给定的起始节点开始,逐层地向外扩展,先访问起始节点的相邻节点,再访问相邻节点的相邻节点,直到遍历完所有可达节点。这一点与DFS的一条路走到黑有着明显区别。
图例如下:
第一层遍历
第二层遍历
2.如何实现
具体BFS算法如下:
1.创建一个队列,并将起始节点入队;
2.将起始节点标记为已访问;
3.当队列不为空时,循环执行以下:
(1)出队一个节点;
(2)访问该节点;
(3)将该节点的所有的未访问的节点入队并更新标记为已访问;
(4)遍历完成
BFS算法的特点是按照层级进行遍历,先访问距离起始节点最近的节点,再次访问距离起始节点远一层的节点。依次类推,由于BFS需要使用队列来辅助实现,因此可以保证每个节点被访问且仅被访问一次。
BFS算法广泛应用于图的遍历,最短路径,连通性检测等问题,也可以解决一些搜索问题,例如在迷宫中找最短路径等。
伪代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
3.对比与发现
DFS与BFS的区别:
BFS遍历节点是先进先出,DFS是先进后出;
BFS是一层一层访问,DFS是一条路一直访问到底,当前节点没有未访问的邻居节点时,然后回溯到上一个节点,不断的尝试,直到访问到目标节点或者是所有节点都已经访问。
BFS适用于求源点与目标节点距离最近的情况,例如:求最短路径。DFS更适合于求解一个任意符合方案中的一个或者遍历所有情况,例如:全排列、拓扑排序、求到达某一点的任意一条路径。
4.例题解析
本题选自洛谷B3625迷宫寻路
题目描述
机器猫被困在一个矩形迷宫里。
迷宫可以视为一个 \(n\times m\) 矩阵,每个位置要么是空地,要么是墙。机器猫只能从一个空地走到其上、下、左、右的空地。
机器猫初始时位于 \((1, 1)\) 的位置,问能否走到 \((n, m)\) 位置。
输入格式
第一行,两个正整数 \(n,m\)。
接下来 \(n\) 行,输入这个迷宫。每行输入一个长为 \(m\) 的字符串,#
表示墙,.
表示空地。
输出格式
仅一行,一个字符串。如果机器猫能走到 \((n, m)\),则输出 Yes
;否则输出 No
。
样例 #1
样例输入 #1
1 2 3 4 |
|
样例输出 #1
1 |
|
提示
样例解释
路线如下:\((1,1)\to (2,1) \to (3,1) \to (3,2)\to (3,3) \to (2, 3) \to (2, 4) \to (2, 5) \to (3, 5)\)
数据规模与约定
对于 \(100\%\) 的数据,保证 \(1 \leq n, m \leq 100\),且 \((1,1)\) 和 \((n, m)\) 均为空地。
思路:bfs
我们可以逐层展开搜索:
- 搜索一步能到达的点;
- 搜索两步能到达的点;
- 搜索三步能到达的点;
这种方法我们成为广度优先搜索(宽度优先搜索,bfs
)。
使用广度优先搜索就要使用到队列,存储待访问的点。
所以我们的 bfs
可以这么写:
- 把起始点 (1,1)(1,1) 入队;
- 如果队列非空:
- 弹出队首 (x,y)(x,y);
- 判断 (x,y)(x,y) 是否非法,若非法,跳过;
- 把 (x,y)(x,y) 相邻的点入队;
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 36 37 38 |
|
5.精选好题推荐(难度升序排列)
1.P1331 海战
4.P2895 [USACO08FEB] Meteor Shower S
PS:再高难度的题的话就不只是针对于BFS来考的了,所以这里不再给出,当然感兴趣同学可以自己上洛谷或者acwing查看
by LosTcrab