一、什么是 A* 寻路算法?
简介
最短路算法可分为三类:
- 直接搜索算法:直接在实际地图上进行搜索,不经过任何预处理;
- 启发式算法:通过启发函数引导算法的搜索方向;
- 静态图搜索算法:被搜索的图的权值不随时间变化(后被证明同样可以适用于动态图的搜索)
A* 寻路选法是一种通常用于路线规划的最短路启发式算法,比如游戏中如何设计怪物绕过障碍物来不断跟随不定时移动的主人公呢?A* 就可以解决这样的问题。
A* 的原理
A* 算法最核心的就是在搜索时尽量利用目前已知的(如工作代价最小、行走路径最短、行走时间最短等),以及从初始状态和当前状态到目标状态估计所需的费用等信息来减少不必要的搜索。
例如在最短路径算法中:我们每次只取出到达终点最有「希望」的路径,避开一些没有意义的到其他点的路径。
没有意义的路径指什么呢?
估价函数
公式为: f ( n ) = g ( n ) + h ( n ) f(n)=g(n)+h(n) f(n)=g(n)+h(n)
- g ( n ) g(n) g(n):表示在状态空间中从初始节点到 V 节点的实际代价,即最短路中 node.cost。
- h ( n ) h(n) h(n):是从 V 到目标节点最佳路径的估计代价。
一般我们这样认为:
- 估价值 h(V) <= V 到目标节点的距离实际值,这种情况下,搜索的点数多,搜索范围大,效率低。但能得到属最优解。
- 如果估价值 h(V) > 实际值,搜索的点数少,搜索范围小,效率高,但不能保证得到最优解。
所以为了让 A* 能在第 K 最短路中有效,一般我们把估计值保持在 [0, dist1[V]]
范围内。
二、第 K 短路的写法步骤
- 建反图,即从结点 V 进行一次最短路算法,得出估价函数 h(v)
- 在 A* 算法,从 S 开始扩展其能扩展到的点,算出估计值:
估计值 = 估价函数 h(v) + 距离起点的实际距离
- 当某个结点率先第 K 次到达终点 E 时,该结点 node 所在路径第 K 短路。
- 返回 node.cost 即可。
方法一:A* 的写法
int A(int S) {
if (dist1[S] == INF)
return -1;
int[] cnt = new int[maxv];
boolean[] vis = new boolean[maxv];
Queue<Node> pq = new PriorityQueue<>((n1, n2) -> (n1.cost + f(n1.v)) - (n2.cost + f(n2.v)));
pq.add(new Node(S, 0));
while (!pq.isEmpty()) {
Node t = pq.poll();
if (vis[t.v])
continue;
int v = t.v, cost = t.cost;
cnt[v]++;
if (v == T && cnt[v] == K)
return cost;
for (int i = head2[v]; i != 0; i = e2[i].next) {
int to = e2[i].to, w = e2[i].w;
pq.add(new Node(to, cost + w));
}
}
return -1;
}
复杂度分析
- 时间复杂度: O ( ) O() O(),
- 空间复杂度: O ( ) O() O(),