CoderXL's Blog

Back

算法与题解 →

用于搜索给定起点 ss 到给定终点 tt 的最短路径。


记号与约定#

G=(V,E)\mathbb{G}=(\mathbb{V},\mathbb{E}) 表示一张图,其中顶点组成的集合是 V\mathbb{V},边组成的集合是 E\mathbb{E}.

dxyd_{xy} 表示图上从点 xx 到点 yy 的最短路径长度。
由于 A* 是单起点单终点最短路,因此用 ss 表示起点,tt 表示终点。
h∗(x)h^*(x) 表示从 xx 到 tt 的最短路径长度,即 h∗(x)=dxth^*(x)=d_{xt}.
h(x)h(x) 是后文会提到的启发式估价函数,尝试在 h∗(x)h^*(x) 尚且未知的情况下去估计它。
g(x)g(x) 表示从 ss 到 xx 的某条路径的长度,具体指哪一条由上下文确定。


A*#

引入#

暴力地来说,如果要搜索从 ss 到 tt 的最短路径,可以用 BFS 搜索所有路径,然后每次用可能的最短路径更新 ss 到 tt 的距离。

然而,极端地说,如果我们事先能知道与 xx 点相连的每个点 yy 到终点的距离 h∗(y)h^*(y),那么我们每次搜索只需要从 xx 走到 arg⁡min⁡yh∗(y)\arg\min\limits_y h^*(y),就能保证我们一直在最短路径上,最终走到终点得到最优解,复杂度只有 O(d)O(d),其中 dd 为最短路径的边数。

显然,我们不可能事先知道 h∗(y)h^*(y),否则答案已经给出,根本不用求解。但是,即使没有 h∗(y)h^*(y),我们能否用一些估计函数 h(y)h(y) 去估计 h∗(y)h^*(y),以达到优化目的呢?

过程#

我们尝试设计一个 h(n)h(n),它在大多数情况下能给出近似的估计。但难免有时会使走到非最优的路径上。此时,我们仍然仅使用 h(n)h(n) 去评判从 ss 经过 nn 到达 tt 的路径的优劣显然是不好的,而应当加入已经走过的真实路径长度 g(n)g(n),即使用 f(n)=g(n)+h(n)f(n)=g(n)+h(n) 来评判。

A* 维护一个优先队列,存储当前能到达的每个节点。每次取出 f(n)f(n) 最小的节点 nn,并将 nn 的所有后继节点处理并弹入优先队列。

然而,这时的 A* 还没有达到它的最佳性能。设想一下,我们的算法好不容易第一次走到了终点,此时得到了终点的 g(t)g(t);但是,由于我们 h(x)h(x) 估计是有误差的,万一先前某个由于 h(x)h(x) 虚高而未被探索的分支,实际上能给出更优的路径,这又该怎么办呢?如果等待算法搜索完所有的路径,其复杂度甚至可能高于 Dijkstra.

所以,我们希望通过良好的 h(x)h(x) 外加严谨的分析推导,保证我们在第一次“走到”(实际上是弹出)终点时,获得的就一定是最优路径。

以下引入两个性质来评价 h(x)h(x) 设计的优劣:

  • 可采纳性 (Admissibility)
∀x∈V, h(x)≤h∗(x)\forall x \in \mathbb{V},\ h(x)\le h^*(x)

即估价函数给出的代价永远不超过真实代价,又称“不虚高”。

  • 一致性(Consistency)/单调性(Monotone)
∀x,y∈V, h(x)≤dxy+h(y)\forall x,y \in \mathbb{V},\ h(x) \le d_{xy} + h(y)

可以理解为估价函数满足三角不等式。当 yy 位于 xx 到 tt 的最短路上时,这个不等式实际上表示 f(x)f(x) 沿最短路单调不降。

下面证明两个命题:

命题 1:若 h(x)h(x) 满足一致性,则任何点 nn 对应的 f(n)f(n) 第一次从优先队列弹出时,此刻的 g(n)g(n) 就是从 ss 到 nn 的最短路径。#

证明: 题目等同于:如果某个 f(n)f(n) 第一次取出时 g(n)g(n) 并非最优,那么 h(x)h(x) 一定不是一致的。

实际上,如果优先队列中同时存在多个不同的 f(n)f(n),那么最小的 f(n)f(n) 一定对应最小的 g(n)g(n)(因为 h(n)h(n) 相同),因此任何时刻取出的 f(n)f(n) 在优先队列内一定最优。

因此要出现题目所说情况,必然是 f(n)f(n) 被弹出后,重新弹入了更优的 f(n)f(n). 设先前在优先队列中的为 f′(n)f'(n),后来进入的为 f′′(n)f''(n),对应的 nn 的前序节点分别为 p,qp,q,对应时刻的 g(n)g(n) 分别为 g′(n)g'(n) 和 g′′(n)g''(n).

从而有 g′(n)=g(p)+dpng'(n)=g(p)+d_{pn} g′′(n)=g(q)+dqng''(n)=g(q)+d_{qn}

此处可以假设从 ss 到 p,qp,q 的最短路径就是 g(p),g(q)g(p),g(q),否则可以令 nn 为 pp 或 qq,从头证明。

由于 f′′(n)f''(n) 在 f′(n)f'(n) 弹出后才进入,因此存在 f′(n)<f(q)f'(n)<f(q).

根据定义: f′(n)=g′(n)+h(n)=g(p)+dpn+h(n)f'(n)=g'(n)+h(n)=g(p)+d_{pn}+h(n) f(q)=g(q)+h(q)f(q)=g(q)+h(q)

从而

g(p)+dpn+h(n)<g(q)+h(q)(#)g(p)+d_{pn}+h(n)<g(q)+h(q) \tag{\#}

同时,由于我们假设 g′(n)g'(n) 并非最优,即 g′(n)g'(n) 劣于 g′′(n)g''(n),也即 g′(n)>g′′(n)g'(n)>g''(n),因此有

g(p)+dpn>g(q)+dqn(*)g(p)+d_{pn} > g(q)+d_{qn} \tag{*}

联立 (#),(∗)(\#),(^*) 两式,就得到了 g(q)+dqn+h(n)<g(q)+h(q)g(q)+d_{qn}+h(n)<g(q)+h(q)

即 dqn+h(n)<h(q)d_{qn}+h(n)<h(q)

不满足一致性 h(q)≤dqn+h(n)h(q) \le d_{qn}+h(n). 证毕。

未完待续 …

Comment seems to stuck. Try to refresh?✨