A∗算法
\(A*\) 算法
这个算法其实就是 dijkstra
的变种,是对于一般的 bfs
的一种优化手段。
首先需要设置一个东西叫做估价函数。普通的 bfs
的估价函数一般取 \(0\)。这个东西如果你要保证一定正确,记起点到当前点的距离为 \(d[i]\),到末尾的真实距离为 \(g[i]\),设你的估价函数是 \(f[i]\),则 \(f[i]\le g[i]\) 就能保证正确。下面我们来证明一下这个结论:
反证法,假设不成立,即当前出队的终点距离不是最优解,即 \(dist>d_{\text{最优}}\),我们设最优解路径上有一点 \(u\),则必有 \(d[u]+f[u]\le d[u]+g[u]=d_{\text{最优}}\),所以 \(dist>d_{\text{最优}}\ge f[u]\)。
而且 A*
算法只能保证终点是最优的,但不能保证中途其他点是最优的。(入队、出队都不一定是最优,且最多保证路径上的点)
如图所示,如果某一个点的估价距离等于它的真实距离都为 \(L\),其他点的估价都是 \(0\),那么就会先从上面一圈绕过来走到后面很远很远的点才发现是错的,所以那个圈和直线交界的位置第一次出队的结果就不是最优解。
可以加一个优化:当一个点的最短距离更新时将其塞入堆中。
估价函数必须非 负。
bfs |
dijkstra |
\(A*\) | |
---|---|---|---|
判重 | 入队判重 | 出队判重 | 不能判重 |