本篇文章主要讲解A*算法,通过一个小案例,来带领同学们理解A*算法,A*算法是什么,底层逻辑是什么,以及在实际中有什么应用
A*算法简介
A*算法:通往最优路径的智能导航者
当我们玩游戏时,NPC总能巧妙地绕过障碍物找到我们;当我们使用地图软件时,它能瞬间规划出多条可行路线。这背后离不开一个强大而优雅的算法——A*(A-Star)算法。
诞生记
1968年,来自斯坦福研究所(SRI)的Peter Hart、Nils Nilsson以及Bertram Raphael共同发表了这一算法。他们的工作属于早期人工智能研究的一部分,旨在为机器(如Shakey机器人)解决路径规划问题。
在A*之前,已有一些路径搜索算法,如:
-
Dijkstra算法:保证找到最短路径,但非常“盲目”,它会像涟漪一样均匀地向所有方向扩展,搜索效率较低。
-
最佳优先搜索(Greedy Best-First-Search):它朝着目标方向“贪婪地”前进,效率高但无法保证找到的路径是最短的,容易误入歧途。
A*算法的伟大之处在于它创造性地融合了这两者的优点。它既像Dijkstra一样,考虑从起点出发的实际代价(g(n)
),保证准确性;又像最佳优先搜索一样,利用到目标的预估代价(h(n)
)来引导搜索方向,提高效率。这种“瞻前顾后”的特性使其成为当时最有效的启发式搜索算法。
核心原理
A*算法之所以高效,在于它有一个简单的决策公式:
f(n) = g(n) + h(n)
这个公式为地图上的每一个节点(位置)计算一个优先级分数 f(n)
。
-
g(n):脚踏实地的事实。代表从起始点到当前节点
n
的实际代价。这是一个已经发生、确切已知的成本,比如已经走过的距离或耗时。 -
h(n):仰望星空的预估。代表从当前节点
n
到目标点的预估代价。这是一个猜测值,由“启发式函数”计算得出。这也是A*算法的“智能”所在。 -
f(n):综合评分。是经过节点
n
的路径的预期总代价。算法永远优先探索开放列表中f(n)
值最小的节点,因为这条路“看起来”是最有希望的。
工作流程与两个列表:
A*算法通过维护两个列表来有条不紊地工作:
-
开放列表 (Open List):一个待检查的“候选节点”优先队列(按
f(n)
排序)。 -
关闭列表 (Closed List):一个已检查完毕、无需再关注的“已探索节点”集合。
启发式算法
h(n)
的设计是A*算法的灵魂,它直接决定了算法的行为和效率。
-
可接受性 (Admissible):这是保证A*能找到最短路径的关键。一个启发式函数必须是可接受的——即它永远不能高估到达目标的实际代价。它必须是一个“乐观的估计”。
-
常见启发函数(以网格地图为例):
-
曼哈顿距离:适用于只能上下左右移动的场景。
h(n) = |x₁ - x₂| + |y₁ - y₂|
-
对角线距离:适用于可以八方向移动(包括对角线)的场景。
h(n) = max(|x₁ - x₂|, |y₁ - y₂|)
-
欧几里得距离:适用于可以向任意方向移动的场景。
h(n) = √((x₁ - x₂)² + (y₁ - y₂)²)
(虽然准确,但计算稍慢,且通常需要乘以一个系数以保证可接受性)
-
浅显理解A*算法
接下来我用一个案例来解决,A*算法的实现逻辑是什么
假设下面是一个地图
A1表示的位置是【0,0】,A2:【1,0】。。。。A5:【4,0】
B2:【0,1】。。。B5:【4,1】
E2:【0,4】。。。E5:【4,4】
然后我要从C1走到C5
第一步,C1会遍历和他相连的五个点【B1,B2,C2,D1,D2】
那这个时候我们就会用到那个很重要的公式
f(n) = g(n) + h(n),且这是我们假设我们使用曼哈顿距离作为我们的启发函数
我们先看B1
B1的位置是【0,1】
C1的位置是【0,2】
根据两者的位置得出B1的 g(n) = =1
C5的位置是【4,2】
根据两者的位置得出B1的 h(n) = |(4-0)| + |(2-1)| = 5
最终得出B1的 f(n) = 1 + 5 = 6
接下来我们看B2
B2 的 g(n) = 约等于 1.4
B2的 h(n) = |(4-1)| + |(2-1)| = 4
最终得出B1的 f(n) = 1.4 + 4 = 5.4
依照上面的方法,我们最终得到五个点的所有综合评分
B1:6
B2:5.4
C2:4
D1:6
D2:5.4
那么这五个点位我们就会放入到开放列表中
同时我们会发现C2的综合评分最优,所以将C2放入到关闭列表中
获取到C2为最优点后,我们来把C2最为下一个路径点
我们可以看到与C2相连接,并且没有被遍历到的点位有【B3,C3,D3】
以B3为例
B3的 g(n) 是指 B3 和 C2 的距离再加上 C2 和 C1 的距离
所以B3的 g(n) = 1.4 + 1 = 2.4
h(n) 的计算方法还是和上面一样
最终我们得出来的这三个点位的最终评分是
B3:5.4
C3:4
D3:5.4
我们可以看出C3的值最优,将C3放入到关闭列表中,其余放入到开放列表中
到这一步,我们就可以像刚才一样,算出来 【B4,C4,D4】三个点位的评分值
B4 = 1.4 + 2 + 2 = 5.4
C4 = 1 + 2 + 1 = 4
D4 = 1.4 + 2 + 2 = 5.4
然后C4放入到关闭列表中
到这一步,我们去获取与C4相连接的点位时,会直接获取到C5,也就是我们的目标点位,到此遍历结束,根据关闭列表可得知,我们的最优路径是
C1 -> C2 -> C3 -> C4 -> C5
到此我的讲解完毕,但是并没有结束,假如是C3是个障碍物,那又是什么情况,该怎么解决,我会放到后面的章节里面去讲解