zoukankan      html  css  js  c++  java
  • 【信息学奥赛一本通 提高组】第四章 广搜的优化技巧

     一、基本算法

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

    二、双端队列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]分别表示正向和逆向将扩展结点的尾指针。

     

  • 相关阅读:
    51 Nod 1086 多重背包问题(单调队列优化)
    51 Nod 1086 多重背包问题(二进制优化)
    51 Nod 1085 01背包问题
    poj 2559 Largest Rectangle(单调栈)
    51 Nod 1089 最长回文子串(Manacher算法)
    51 Nod N的阶乘的长度 (斯特林近似)
    51 Nod 1134 最长递增子序列(经典问题回顾)
    51 Nod 1020 逆序排列
    PCA-主成分分析(Principal components analysis)
    Python中cPickle
  • 原文地址:https://www.cnblogs.com/Osea/p/11214441.html
Copyright © 2011-2022 走看看