一、最基本的搜索算法:回溯算法
回溯算法是所有搜索算法中最为基本的一种算法,其采用了一种“走不通就掉头”思想作为其控制结构。
二、搜索算法分类:bfs与dfs
dfs:栈的思想(先进后出)优先兄弟节点。容易超时,多用于求可行解。
bfs:队列的思想(先进先出)优先儿子节点。容易消耗大量内存,多用于求最优解。
总结:搜索算法从最终的算法实现上来看,都可以划分成两个部分——控制结构(扩展节点的方式)和产生系统(扩展节点),
而所有的算法优化和改进主要都是通过修改其控制结构来完成的。其实,在这样的思考过程中,我们已经不知不觉地将一个具体的问题抽象成了一个图论的模型——树,
即搜索算法的使用第一步在于搜索树的建立。
第二部分 搜索算法的优化
一、双向广度搜索
广度搜索虽然可以得到最优解,但是其空间消耗增长太快。但如果从正反两个方向进行广度搜索,理想情况下可以减少二分之一的搜索量,从而提高搜索速度。
二、分支定界(俗称剪枝)
分支定界实际上是A*算法的一种雏形,为了有效地选择下一扩展结点,以加速搜索的进程,在每一活结点处,计算一个函数值(限界),
并根据这些已计算出的函数值,从当前活结点表中选择一个最有利的结点作为扩展结点,使搜索朝着解空间树上有最优解的分支推进,以便尽快地找出一个最优解。
三、A*算法
A*算法中更一般的引入了一个估价函数f,其定义为f=g+h (f必须单调递增,切越小越好)。其中g为到达当前节点的成本,而h表示对从当前节点到达目标节点的耗费的估计。
A*算法的控制结构与广度搜索的十分类似,只是每次扩展的都是当前待扩展节点中f值最小的一个,如果扩展出来的节点与已扩展的节点重复,则删去这个节点。
如果与待扩展节点重复,如果这个节点的估价函数值较小,则用其代替原待扩展节点。
四、A*+小顶堆
如果每次排序找扩展节点中f最小的元素,那么排序的工作量可以说是很大的,即使是快排,程序也不够快!
这里,可以想到,由于需要动态的添加元素,动态的得到程序的最小值,我们可以维护一个小顶堆,这样的效果就是。
每次取最小元素的时候,不是用一个n*Log(n)的排序,而是用log(n)的查找和调整堆。
五、IDA*
IDA*算法就是基于迭代加深的A*算法。迭代加深分两步走:
1、枚举深度(H值逐渐递增枚举,有解情况必是最有值)。
2、根据限定的深度进行DFS,并且利用估价函数进行剪枝。
由于改成了深度优先的方式,与A*比起来,IDA*更实用:1.不需要判重,2.不需要排序,3.空间需求减少。
六、记忆化搜索(深搜+动态规划)
搜索到的一些解用动态规划的那种思想和模式作一些保存。
eg:给定一个8 * 8的国际象棋棋盘。给出棋盘上任意两个位置的坐标,问马最少几步可以从一个位置跳到另外一个位置.
if dp[x2][y2] > dp[x1][y1] + 1 then dp[x2][y2] = dp[x1][y1] + 1 继续搜下去
else 没有必要搜下去了 return
八数码问题的八重境界:
境界一、 暴力广搜+STL
境界二、广搜+哈希
境界三、广搜+哈希+打表
境界四、双向广搜+哈希
境界五、A*+哈希+简单估价函数
境界六、A*+哈希+曼哈顿距离
境界七、A*+哈希+曼哈顿距离+小顶堆
境界八、IDA*+曼哈顿距离