<福州集训之旅Day2> | BFS与搜索优化 |

搜索学习第二篇

广搜与深搜剪枝


<更新提示>

<第一次更新>仍讲例题与思想,不附代码。


<正文>

BFS

与DFS相对应,BFS(广度优先搜索)即由浅到深逐层遍历,在一个状态拓展完后,先拓展其他同层状态。

在使用BFS进行搜索时,我们通常使用一个先进先出的队列来维护未处理的状态,同时,需要保证队列中不存在两个相同的状态。因此,也需要一个数组来标记该状态是否出现过。

<图例详解>

这里写图片描述

如图,若使用BFS从s点到T点,是怎样的过程呢?

第一步:将s点加入队列,并标记为已经搜索过,并沿s点进行拓展搜索:这里写图片描述

第二步:搜索,我们由s点的连线拓展出两个新的节点,1与2,并将其加入队列并标记,同时,s点出队。
这里写图片描述

扫描二维码关注公众号,回复: 1892394 查看本文章

第三步:重新执行该流程,我们由1开始,将其出队,并将它所链接的节点依次入队,继续搜索。同时,标记不能忘记,如果搜索到标记过的状态,说明该状态曾经搜索到过,直接跳过即可。如图,1也链接了2节点,但2已经入队并标记过,再次拓展时跳过即可。

这里写图片描述

接下来就是对2,3步的循环往复,这里将简要说明并给出队列图示。
2拓展并出队,4入队。
这里写图片描述

第四步:接下来,我们由3节点的拓展找到了T节点,即目标节点。此时,经过我们的遍历,已经找到了一条从s通往T的路径。这便是广搜基本的原理了。
这里写图片描述

由上的BFS模拟过程中,我们不难发现,BFS由浅至深遍历,当我们遍历到任意一个点X时,到达X的状态就是由起点到X中间经过边最少的节点,所以,如果图的边没有权值,那么BFS找到的就是最短路。

对于基本的BFS搜索,我们就有了如下框架:
维护一个队列q,已经其数组vis[]表示其是否曾被遍历过,假设以最短路从初始状态S到达目标节点T,那么由如下过程:
1 将S加入队列,令vis[S]=true
2 检查队列是否为空,如果为空则遍历结束,否则取出队头状态X
3 依次取X状态的所有拓展,并令X的拓展状态i即vis[Xi]=true,如果已经为真,则跳过这个状态。如果Xi为目标状态T,则找到了从S到T的最短方式,否则继续拓展新的状态。

<例1:BFS的状态设计>
拯救行动
骑士(R)在一个n*m的牢房中准备解救公主(A),矩阵中的每项可以表示空地(.),墙壁(#),守卫(S)。假设骑士可以往上下左右四个方向移动,每移动一个需要花费一个单位时间,如果必要杀死守卫时,需要额外花费一个单位时间。给定n*m的矩阵,请计算拯救成功花费的最短时间。
解析:假设没有守卫,那么直接进行BFS直到找到公主即可。但如果有守卫,我们需要将第一次解决守卫的过程加入BFS的状态(守卫不会复活),因为在最短路中一个格子不会到达两次,所以我们考虑用(当前位置,0/1)来记录状态,0表示该位置没守卫,1则表示有守卫,从(当前位置,1)转到(当前位置,0)需要花费一个单位时间来杀手守卫。这样就能清楚的表示BFS的状态了。

小结

由此,我们对BFS和DFS进行对比:
DFS的整体过程基于搜索回溯,其在搜索树上往深处搜索,只记录当前如今的状态,但其搜索的过程不保证解的最优性。同时DFS还相当耗时——其本质为枚举所有解,故适用于寻找所有解,不适用于寻找最优解。
然而BFS的整体过程基于带拓展节点的队列,其搜索树上按照由浅至深的方式不断对节点进行拓展,使待拓展的节点越来越多。在BFS的过程中,到大每一个状态的1方式都是最优的,但代价时要庞大的队列记录节点,以更高效的方式记录一个节点是否入队,故BFS更适于寻找最优解,但如果最优解太深,容易耗费大量的空间。

搜索优化

搜索的本质上需要遍历所有的状态,如果状态数太多,那么搜索就会很低效。如果我们能够提前将一些一定不符合要求或一定不是最优解的搜索提前结束的话,搜索的效率就能提高。从搜索数上说,这就相当于减掉一些不含目标节点的子树分支,所有这种搜索优化就叫剪枝。剪枝是一种重要的优化搜索方式,显然,剪枝越靠近根节点效果越好。

<例1:剪枝的分析>

给出n根小棒的长度,已知这n根小棒由若干根原棒分解而来,求原棒的最小可能长度L。

解析:这里,我们对剪枝进行分析:
1 记这n根木棒的长度和为S,最长长度为M,那么显然有:L>=M且L|S
2 将小木棒从长到短排序,搜索时跳过长度相同的木棒
3 选取每一组木棒时,必须选剩下木棒中最长的拿一根

仔细思考,我们在用DFS搜索枚举L时,这三条剪枝都是有效且极其有用的,这便是简单的剪枝策略。

小结

对于剪枝,通常可以总结为这两种方式:
可行性剪枝:如果本次的搜索根本不符合要求,那就根本不必搜索,直接退出即可。
最优性剪枝:经过推理判断,如果本次的搜索根本没有曾经的搜索所得出的解优秀,那也不必搜索,直接退出。


<后记>

保留了一道8数码问题没有讲(因为我自己也不会),以后再补吧。
关于广搜的模板,最近也会附上代码的。


<废话>

猜你喜欢

转载自blog.csdn.net/prasnip_/article/details/79284654
今日推荐