还有一类广度优先搜索的题目会在数字的扩展和搜索上,我们假设需要从起始状态到达目标状态需要40步,每次扩展最多产生2种状态,那么最差情况下,状态数量会到达
2
40
2^{40}
240。很明显,如果我们不使用一些措施,我们的队列中必然无法存储如此多的情况,最终导致空间超限。
有没有什么好的解决办法呢?其实很容易能想到,我们可以从起始状态和目标状态一起开始搜索,类似于多起点BFS。
一般我们有两种方案完成双向广度优先搜索,一种类似于多起点BFS,但是在记录状态时将其分开,一旦从一端搜到已经被另一端访问过的元素,那么我们可以认为已经找到了方案。
伪代码是:
将 起始状态 和 目标结点 入队
标记起始结点为 1
标记目标结点为 2
while(队列不为空)
{
从队首扩展出新个结点
如果 新扩展出的结点已经被其他数字标记过,表示已经搜索到了一种方案,算法结束。
如果新个结点是从起始状态扩展来的,那么将这个该结点标记 1 并入队
如果新个结点是从目标结点扩展来的,那么将这个该结点标记 2 并入队
}
另一种方案则通过一些数据结构来完成,首先我们从起始状态开始进行一定步数的广度优先搜索,如果最终没有搜到目标结点,则将这些状态全部放入一个 set 中,接着我们从结尾开始进行广度优先搜索,每次在 set 中检查新扩展的状态有没有被产生过。注意从结尾开始的广度优先搜索也需要限定最大步数。
另外需要大家小心的是,在进行双向广度优先搜索时,从起始状态到目标状态和反过来,从目标状态到起始状态的状态变化往往是不同的,这需要大家将正向转移进行一些变化,在代码中切记。