【綜合演算法】A*演算法
A*演算法
A*演算法;A*(A-Star)演算法是一種靜態路網中求解最短路徑最有效的直接搜尋方法,也是許多其他問題的常用啟發式演算法。注意是最有效的直接搜尋演算法。之後湧現了很多預處理演算法(ALT,CH,HL等等),線上查詢效率是A*演算法的數千甚至上萬倍。
在遊戲、優化領域,A*演算法是很重要的一個演算法。例如RTS遊戲中控制移動單位到另外一個地點,玩家只需要在指定地點下達指令,移動單位可以自動搜尋最好的路徑抵達目的地。
在路徑搜尋方面,A*演算法的目標是找到當前已知約束條件下的最優路徑。由於A*演算法是直接搜尋方法,沒有全域性優化,並且我們並不知道實際情況有多複雜,所以A*演算法最後不一定能得出全域性最短路徑,而是得到當前已知約束條件下的最優路徑,甚至可以根據實際情況,在路徑搜尋速度和路徑搜尋質量上取得平衡。
A*演算法可以看做迪傑斯特拉最短路徑演算法和最優貪心演算法的綜合。相比傳統的迪傑斯特拉演算法,A*演算法在每個路徑節點的權值計算有所不同。A*演算法的權值計算表示為:
一般情況下,設上一級搜尋的節點為n,其權值為
另外,格子的走法也需要設定。普通的方格路徑,我們需要考量是否可以斜著行進,既可以設定當前點的斜向鄰點是否可以移動,也可以只是設定斜向鄰點具有稍微大點的權值;在《文明》系列遊戲中,單位方格則是六邊形方格,角色可以選擇移動到周圍六個方格。
A*演算法的虛擬碼非常簡單,百度百科摘錄如下:
建立兩個表,OPEN表儲存所有已生成而未考察的節點,CLOSED表中記錄已訪問過的節點。計算算起點的h(s);將起點放入OPEN表;
while(OPEN!=NULL)
{
從OPEN表中取f(n)最小的節點n;
if(n節點==目標節點)
break;
{
計算f(X);
if(X in OPEN)
{
if(新的f(X)小於OPEN中的f(X)){
把n設定為X的父親;
更新OPEN表中的f(n);
}
if(X in CLOSE)
continue;
if(X為全新節點)
{
把n設定為X的父親;
求f(X);
並將X插入OPEN表中;//還沒有排序
}
}//endfor
將n節點插入CLOSE表中;
按照f(n)將OPEN表中的節點排序;//實際上是比較OPEN表內節點f的大小,從最小路徑的節點向下進行。
}//endwhile(OPEN!=NULL)
做完計算之後,如果遇到目標點,那麼從目標點開始沿著父節點向上回溯到起始節點,然後對搜尋路徑執行反向操作,就得到了起始點到目標點的路徑。
讀懂上述程式碼就知道A*演算法的實現方法,可以說邏輯上比較簡單。存在的問題主要在如何給出
下面給出一部分使用曼哈頓度量計算的結果圖和說明,圖中包含一個白色C型障礙物,左邊的小白點是起始點,右邊的小白點是目標點,灰色區域表示搜尋範圍:
曼哈頓距離權值
曼哈頓距離權值
曼哈頓距離權值
曼哈頓距離權值