A* 搜索算法
A* 搜索:梦想与现实的精密天平
算法背后的故事:给“Shakey”一个大脑
20 世纪 60 年代末,斯坦福国际研究院 (SRI) 的研究人员正在研制 Shakey——世界上第一台能够对自己的行动进行逻辑推理的通用移动机器人。Shakey 需要在充满房间和走廊的复杂世界中移動。
当时已有的工具并不够用。Dijkstra 算法太慢了——它像一個不斷擴張的圓圈一樣向所有方向探索,把大量的算力浪費在了那些遠離目標的路徑上。團隊成員(Peter Hart, Nils Nilsson, 和 Bertram Raphael)意識到:如果機器人知道目標在哪裡,它就應該利用這個“夢想”來引導自己的腳步。
他們將 Dijkstra 算法的數學嚴謹性與一種“啟發式 (Heuristic)”——也就是有根據的猜測——結合在一起,創造了 A*。這是現代啟發式搜索的誕生。
为什么需要它?
想象你正從巴黎開車去柏林。
- Dijkstra 算法會探索通往倫敦、馬賽甚至大西洋的路徑,僅僅因為它們離巴黎很“近”。
- *A 算法**則會死死盯着柏林。它會優先考慮那些真正指向東方的道路。
在工程界,A* 是 遊戲 AI 和 GPS 導航 的首選,因為它極大地減少了計算機需要檢查的路徑數量。
算法是如何“平衡”的
A* 算法的秘密隱藏在一個簡潔而深刻的等式中:。
這個算法就像一個行路人,時刻關注著兩件事:
- (現實): “從起點走到這裡,我已經花了多少成本?” 這是來自過去的硬數據。
- (夢想): “從這裡到終點,大概還剩多少路?” 這就是 啟發式估算 (Heuristic)。我們還不知道確切答案,所以我們先用直線距離(鳥飛距離)來代替。
在每一步中,A* 不只是挑選“最近”的節點,而是挑選那個 現實 + 夢想 總和最低的節點。
如果夢想 () 為 0,它就退化成了 Dijkstra。如果夢想太大,它可能會對你撒謊並找到一條爛路。但只要夢想是 “樂觀”的(即它永遠不會高估真實距離),A* 就保證能找到完美的捷徑,同時無視地圖上 90% 的無效區域。
工程決策:指南針的選擇
A* 是世界上最流行的路徑規劃算法,但它需要一個 啟發式函數。選擇合適的函數是工程師最重要的任務:
- 歐幾里得距離: 適用於可以在任何方向移動的開放世界遊戲。
- 曼哈頓距離: 最適合城市網格或拼圖遊戲,因為你只能上/下/左/右移動。
A* 是“聰明人”的選擇。它比 Dijkstra 快,比純粹的貪心搜索準。它是任何已知目的地系統的黃金標準。
实现参考 (Python)
import heapq
def a_star(graph, start, goal, heuristic):
# g_score: 从起点到当前节点的实际代价 (现实)
g_score = {node: float('inf') for node in graph}
g_score[start] = 0
# f_score: 现实 + 梦想 (预估的总代价)
f_score = {node: float('inf') for node in graph}
f_score[start] = heuristic(start, goal)
# 优先队列存储: (f_score, 节点ID)
pq = [(f_score[start], start)]
while pq:
_, current = heapq.heappop(pq)
if current == goal:
return g_score[goal] # 到达终点!
for neighbor, weight in graph[current].items():
# 计算如果走这条路,到达邻居的代价
tentative_g = g_score[current] + weight
# 如果这条新路比之前记录的任何路径都要好
if tentative_g < g_score[neighbor]:
g_score[neighbor] = tentative_g
# 核心逻辑:现实 + 梦想
f_score[neighbor] = tentative_g + heuristic(neighbor, goal)
heapq.heappush(pq, (f_score[neighbor], neighbor))
return float('inf')
# 启发式函数示例:曼哈顿距离
# def manhattan_dist(p1, p2):
# return abs(p1.x - p2.x) + abs(p1.y - p2.y)小结
A* 告訴我們,了解過去很重要,但對未來有遠見才能讓我們更高效。通過在腳下的重量與目標的方向之間取得平衡,A* 在現實世界的混亂中找到了那條最優的路。
