双向BFS

双向BFS算法思想

理解

双向BFS适用于已经直到了起点和终点的状态下使用,从起点和终点两个方向开始进行搜索,可以极大地提高单向BFS的搜索效率。

可以设置两个队列,一个队列保存从起点开始搜索的状态,另一个队列用来保存从终点开始搜索的状态,当两个队列都非空时才能继续进行循环。循环内不断对元素较少的队列进行BFS操作(以免退化为单向BFS),每次操作从队列弹出一个元素,与该元素相连的后续未访问元素压入队列中。如果某一个状态出现相交的情况,那么就出现了答案。

当两种颜色相遇的时候,说明两个方向的搜索树遇到一起,这个时候就搜到了答案。
在这里插入图片描述

针对扩展方式还可以进行优化——交替逐层扩展。由于两端扩展节点个数可能差别很大,所以每次选择节点个数少的队列进行扩展。return的条件仍为有节点重叠。

正确性证明如下(证明不会因为提前break而错过最优解):

假设当前得到最优解为X,不失一般性,假设X现在是从起点搜索到的,则X已经被终点搜索过了,所以才终止搜索。使用反证法证明,假设存在最优解Y。

  • 若X和Y在同一层,则当且仅当从终点搜索时Y位于X前面层,Y才为最优解。设从起点搜索Y的前一个节点为z,由于终点方向从Y所在层,扩展到X所在层,这个过程是连续,所以在这个过程中会首先扩展到z,则z被当做最优解,程序return。如下图所示:

  • 在这里插入图片描述

  • Y位于X的后面,令X和Y相隔i层,则Y为最优解的充分条件为:从终点方向,Y与X的层数之差大于i,记为j。令起点方向上,z是y的前j个节点。那么从终点方向搜索时,z应该不晚于x被搜到。因此也不会错过最优解。如下图所示:

  • 在这里插入图片描述

所以使用交替逐层能保证算法正确性。

我们知道,BFS是往广处去搜索,我们把这想象成一个以起点为圆心的一个圆,每向前走一步,就是圆的半径增大一个单位,而圆的每个单位面积上是一种状态,当圆增大到目标点那么大时,找到了答案,搜索结束。那么显然的,当半径较大时,每走一步就会有十分大量的状态需要来储存( S = π r 2 S=\pi r^2 S=πr2)。通常的,我们用“判重”的方法来解决,但是在这里,还有一种优化方法:双向BFS:

双向搜索适用于起点和终点状态都很明确的搜索题。试想,我从起点推算到终点,与我从终点推算到起点,最后得到的最少步骤数一定是相等的,所以我们可以从起点和终点同时搜索。同样用圆来打比方,假设以起点为圆心画圆时,其半径为 r r r,以终点为圆心画圆时,其半径为 R R R,那么显然有: π r 2 + π R 2 ≤ π ( r + R ) 2 \pi r^2+\pi R^2\leq \pi (r+R)^2 πr2+πR2π(r+R)2

蓝色圆是从起点出发搜索得到的圆,绿色圆是 从终点出发搜索得到的圆,起点和终点同时搜索,双向BFS,此时只需要搜索的状态空间是 π r 2 + π R 2 \pi r^2+\pi R^2 πr2+πR2,而如果我们只是用单向的BFS算法,那么得到的状态空间是 π ( r + R ) 2 \pi (r+R)^2 π(r+R)2,显然 π r 2 + π R 2 ≤ π r 2 + π R 2 + 2 π r R \pi r^2+\pi R^2\leq \pi r^2+\pi R^2+2\pi rR πr2+πR2πr2+πR2+2πrR。由此可知,双向BFS效率更高。

在这里插入图片描述

双向BFS的正确做法是交替逐层搜索,而不是交替节点搜索,为什么交替节点搜索是错误的呢?

在这里插入图片描述

求S-T的最短路,交替节点搜索(一次正向节点,一次反向节点)时:

  • Step 1 : S –> 1 , 2
  • Step 2 : T –> 3 , 4
  • Step 3 : 1 –> 5
  • Step 4 : 3 –> 5 返回最短路为4,错误的,事实是3,S-2-4-T

正确做法的是交替逐层搜索,保证了不会先遇到非最优解就跳出,而是检查完该层所有节点,得到最优值。也即如果该层搜索遇到了对方已经访问过的,那么已经搜索过的层数就是答案了,可以跳出了,以后不会更优的了。当某一边队列空时就无解了。

为什么要优先选择队列元素少的进行BFS呢?

因为长度小的队列扩展出的元素数量少,效率高。提供速度的关键在于使状态扩展得少一些,所以优先选择队列长度较少的去扩展,保持两边队列长度平衡。这比较适合于两边的扩展情况不同时,一边扩展得快,一边扩展得慢。如果两边扩展情况一样时,加了后效果不大,不过加了也没事。

况不同时,一边扩展得快,一边扩展得慢。如果两边扩展情况一样时,加了后效果不大,不过加了也没事。

在这里插入图片描述

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

卷心菜不卷Iris

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值