A*搜索算法
2018-03-17 18:15:47
A*搜索算法是最短路徑問題中另一個非常經典的算法。A*算法常用於遊戲中的NPC的移動計算,或網絡遊戲的BOT的移動計算上。
該算法綜合了Best-First Search和Dijkstra算法的優點:在進行啟發式搜索提高算法效率的同時,可以保證找到一條最優路徑(基於評估函數)。
下面舉例說明這個算法的過程,舉例用的網絡如下,從S - > G:
方法一、僅采用積累距離
算法流程:
Get the end,break
|
Initial Queue --> Test First Path --> Extend First Path , sorted by ACC
|——————————|
由於我每次都擴展的最小的積累距離值,所以第取出G的時候,就是G為最短路確定的時候,因為任何其他的路都比S - ?G長,而且日後也不可能更短。
其實這就是Dijkstra算法。當然在這裏,我做了很多無效的extend,如果維護一個extend表,那麽效率將會有很大的提升。
方法二、啟發式距離 + 擴展列表
上面的Dijkstra方法不好的地方是很明顯的,這種方法沒有方向性,是一種發散式的搜索,事實上,運行一遍Dijkstra可以將源點到其他所有點的最短路徑求出來。
然而,在很多問題中,我們並不需要源點到其他結點的距離信息,我們只關系源點到目的地的最短路徑,這時候就可以使用啟發式的距離,來讓路徑的生成變得有方向性。
具體做法就是將上面的選擇過程中積累長度變成積累長度 + 啟發式距離。
在找到一條路徑後還需向下探查,直到其他路都絕無可能為止。
另外,這裏加上了擴展列表,也就是已經擴展過的不會再繼續擴展,這就是A*算法的思路。
A* = 分支限界 + 擴展列表 + 可容許啟發式路徑。
function A*(start,goal) closedset := the empty set //已經被估算的節點集合 openset := set containing the initial node //將要被估算的節點集合,初始只包含start came_from := empty map g_score[start] := 0 //g(n) h_score[start] := heuristic_estimate_of_distance(start, goal) //通過估計函數 估計h(start) f_score[start] := h_score[start] //f(n)=h(n)+g(n),由於g(n)=0,所以省略 while openset is not empty //當將被估算的節點存在時,執行循環 x := the node in openset having the lowest f_score[] value //在將被估計的集合中找到f(x)最小的節點 if x = goal //若x為終點,執行 return reconstruct_path(came_from,goal) //返回到x的最佳路徑 remove x from openset //將x節點從將被估算的節點中刪除 add x to closedset //將x節點插入已經被估算的節點 for each y in neighbor_nodes(x) //循環遍歷與x相鄰節點 if y in closedset //若y已被估值,跳過 continue tentative_g_score := g_score[x] + dist_between(x,y) //從起點到節點y的距離 if y not in openset //若y不是將被估算的節點 add y to openset //將y插入將被估算的節點中 tentative_is_better := true //暫時判斷為更好 elseif tentative_g_score < g_score[y] //如果起點到y的距離小於y的實際距離 tentative_is_better := true //暫時判斷為更好 else tentative_is_better := false //否則判斷為更差 if tentative_is_better = true //如果判斷為更好 came_from[y] := x //將y設為x的子節點 g_score[y] := tentative_g_score //更新y到原點的距離 h_score[y] := heuristic_estimate_of_distance(y, goal) //估計y到終點的距離 f_score[y] := g_score[y] + h_score[y] return failure function reconstruct_path(came_from,current_node) if came_from[current_node] is set p = reconstruct_path(came_from,came_from[current_node]) return (p + current_node) else return current_node
A*搜索算法