【信息学奥赛一本通 提高组】第四章 广搜的优化技巧

 一、基本算法

  如果我们把问题状态空间类比成一个图,那么广度优先搜索就相当于对这个图的广度优先遍历。类似地,我们依然借助一个队列来实现广度优先搜素,起初队列中仅包含起始状态,在广度优先搜索的过程中,我们不断地从队头取出状态,对于该状态面临的所有分支,把沿着每一条分支到达的下一个状态(如果尚未访问过或者能够被更新成更优的解)插入队尾。重复执行上述过程直到队列为空

二、双端队列BFS

  在最基本的广搜优先搜索中,每次沿着分支的扩展都记为“一步”,我们通过逐层搜索,解决了求起始状态到每个状态的最少步数的问题。这其实等价于在一个边的边权均为1的图上执行广度优先遍历,求出每个点相对于起点的最短距离(层次)。并且我们知道,每个状态在第一次被访问并入队时,计算出的步数即为所求。然而,如果图上的边权不全为1呢?换句话说,如果每次扩展都有各自不同的“代价”,我们想求出起始状态到每个状态的最小代价。

三、Hash判重

  深度优先搜索的另外一类应用——给出起始和目标状态,以及状态转移的规则,要求找到一条到达目标状态的路径或者方法。这类问题我们称它为路径寻找问题(例如,走迷宫问题),解决这类问题最有效的算法选取合适的方法构造Hash表。

  在路径寻找问题中,经常会遇到走回头路的问题,所以在搜索的过程中都必须做一件事,就是判重。判重是决定程序效率的关键,而如何构造一个优秀的Hash表决定了一切。一个好的Hash函数可以在很大程度上提高程序的整体时间效率和空间效率。

  Hash表的构造方法一般有;

  1、状态压缩——运用2进制来记录状态。

  2、直接取余法——选取一个质数M作为除数。

  3、平方取中法——计算关键值平方,再取中间r位形成一个大小为2r的表

  4、折叠法——把所有字符的ASCII码加起来。

四、双向宽度搜索

  从正反两个方向进行宽度优先搜索,可以大大减少搜索量,提高搜索速度。

  从起始状态和目标状态两个方向同时进行扩展,如果两颗解答树在某个结点第一次发生重合,即可终止此搜索过程,则该结点所连接的两条路径所拼成的路径就是最优解。

  

1、双向宽度优先搜索通常有两种搜索方法

  1、两个方向交替扩展

  2、选择结点个数较少的那个方向先扩展。

  方法2只需要略加修改控制结构,每次while循环时值扩展正反两个方向中结点数目较少的那一个,可以使两边的发展速度保持一定的平衡,从而减少总扩展结点的个数,加快搜索速度。

  很明显方法2优于方法1

2、算法说明

  设置两个队列,Q[2][maxn],分别表示正向和逆向的扩展队列。

  设置两个头指针L[2]分别表示正向和逆向将扩展结点的头指针。

  设置两个尾指针R[2]分别表示正向和逆向将扩展结点的尾指针。

 

原文地址:https://www.cnblogs.com/Osea/p/11214441.html