估估估
开估!
记录一下A*和启发式搜索的笔记
启发式搜索
是的我们启发式搜索就是来混分的(划掉)
实际上启发式搜索你可以看作一种形式化的剪枝
举个例子
正常人剪枝: 越界了?剪掉;不符合?剪掉;没有最优解好?剪掉;不可能比最优解好?剪掉……
启发式搜索采用一个估价函数来解决这些问题:比如我们用一个f(x)来记录现在这个状态下我们可能获得的最大收益
很明显, 如果是一个正常的背包问题,我们需要两个参数来唯一确定这个值
但是如果复杂度限制在了\(n \log n\)级别呢?很明显这个时候我们无法得到一个准确的值, 所以这个时候我们的估价函数可以是固定一个参数的最大/最小值来帮助我们剪枝。
这个时候我们的复杂度(加上记忆化等优化)便可以低于平方级别
至于搜索本身高额的复杂度, 就看你剪枝的实力了(
例题:采药(虽然题目过水但是可以体会一下思想)
同时,启发式搜索的思想决定了他的写法很容易debug(这是后话)
A*
本质是bfs的改进算法。
事实上,和dij的思想是一样的。我们定义一个估价函数f(x) = g(x) + t(x);
其中g(x)表示当前我们已经走过的路经长度,t(x)表示我们还需要走的路经长度
但是如果我们已经可以求出来这些东西了要你何用(划掉)
所以这里的t(x)实际上是一个预估的值(要求至少要比我们真正的值要大)
然后仿照dij, 设好初始状态之后就可以塞进初始队列里面然后不断的更新未出队的点的信息就可以了。
如果我们的t函数满足三角不等式, 那么A*不会讲重复节点反复入队。
例题:八数码
事实上,最令我惊讶的一点是A*是一种k短路的一种伪正解写法(复杂度错误但是能过源数据)
具体而言, 我们反向建图然后以终点为起点跑一遍单源最短路作为g(x), 然后我们再记录跑到当前点的总路程和当前是第几次跑到, 当目标节点第k次被跑到时记录答案即可。
复杂度\(O(kn\log n)\)已经被hack了, 甚至好像有正确性错误但是不知道在哪🤷