一:概述
a*演算法在遊戲中應用是十分廣泛的,許許多多的遊戲在尋路方面都會考慮使用該演算法(當然除該演算法外,前輩們也想出很多其他辦法),它是一種啟發式的尋路搜尋演算法。今天這邊重點全面分析**a*演算法。
二:術語
start-node :起始節點。即:使用者請求尋路時的起點
end-node :目標節點/稱之為結束節點/終點。即:使用者請求尋路的終點/目的地點
current-node :當前節點。即:當前正在分析的節點
adjacency-node:鄰接節點。即:與當前節點相鄰接的節點。如:在 n x m 型地圖中,乙個節點的鄰接節點是指與該相連的周邊8個節點,即稱為鄰接節點。
evaluate-func :估值計算函式(即:h-value值計算函式)
g-value :從 start-node 節點到 current-node 節點的實際代價
h-value :從 current-node 到 end-node 節點的估價值/預估代價
f-value :指 current-node 的 g-value + h-value 和值,即:估價值。其定義是:從 start-node 經過 current-node 節點到達 end-node 節點的估價值。(或許可以簡單理解為 current-node 的 a* 值吧)
open-table :開表。即:待考察節點列表
close[d]-table :閉表。即:已考察節點列表(close後面加不加 d,完全不重要,不需要糾結)
三:演算法思想
整體上,a*演算法主要是將節點劃分為未考察的、待考察的以及已考察的三大類。剛開始時的(所有)節點都是未考察的,而待考察的節點則全都被放在open-table中,所有已經被考察過的節點全都放在close-table中。因此,明顯的 open-table、close-table 表起初都是空的。演算法細節如下:
step_001:重置資料;如:需要重置 start-node 的 g-value = 0;h-value = evaluate-func(........);
step_001:將 start-node 入 open-table;
// 第一層迴圈邏輯開始
step_002:取出 open-table 中 f-value 值最小的節點作為 current-node,並做如下處理。(剛開始時,f-value 最小肯定是 start-node,因為表中只有這個節點)
step_003:如果 current-node 不存在,則尋路失敗退出
step_004:如果 current-node 為 end-node,則尋路成功退出,並將 end-node 的前驅節點置為 current-node,然後返回由 end-node 逆序倒推其前驅節點直到 start-node 的所有節點組成的路徑返回
step_005:將 current-node 入 close-table;
// 第二層迴圈開始
step_006:逐個遍歷 current-node 的 adjacency-node,並做如下處理
step_007:如果 adjacency-node 在閉表中,則不做任何處理
step_008:如果 adjacency-node 不在開表中,則更新其 g-value、h-value 值;並將該 adjacency-node 的前驅節點置為 current-node 節點,最後再將 adjacency-node 入 open-table
step_009:如果 adjacency-node 已在開表中,則比較如果從當前的 current-node 到該 adjacency-node 的 g-value 是否會比 adjacency-node 此時的 g-value 值更優(即:更小)。
如果不會更優,則不做任何處理;
如果會更優,則將 adjacency-node 的 g-value 值更新為從當前 current-node 到 adjacency-node 的 g-value 值,並將 adjacency-node 的前驅更改為當前的 current-node節點
step_011:只要 open-table 表非空,則繼續回到 step_002 處理
四:討論
a*演算法思想其實非常容易理解,並且其在尋找單源最短路徑方面算是速度最為快速的。與dijkstra演算法相比,因為a*是啟發性的搜尋演算法,其是更有目的性地(依賴啟發函式的指引下)向目的節點逼近,它不能說是盲目性地搜尋演算法。而dijkstra演算法則不同,它是盲目性地按演算法規則一步步尋找下去。因此,dijkstra演算法是適合單源到其他所有節點的最短路徑的搜尋演算法。當然,從搜尋的結果路徑來看,dijkstra演算法從源節點到任何節點的路徑肯定都是最短的,而a*卻未必,因為a*的啟發函式只是預估、估算出代價罷了,沒辦法保證不把路徑給帶偏。只是這種路徑偏離一般情況下是不會很離譜的,多數情況下也都會非常接近最短路徑的,這主要是要看啟發函式如何選擇,不同的啟發函式結果路徑可能會不一樣。再從時間複雜度上看,dijkstra演算法的時間複雜度,如果是任何兩點間的最短路徑的話,演算法時間複雜度為o(n^3),而a*則要好很多,從上面演算法思想中可以大約看出,時間代價最大的是在每一層迴圈遍歷處理所有節點環節上,如果以 n x m 地圖來例,且每個節點鄰接節點算上斜角的也才8個,記為 m。因此明確兩點間的a*尋路時間複雜度 t(n) = n * (c1 + m) + c2,因此,時間複雜度為漸近o(n),而任何兩點間的a*尋路時間複雜度為o(n^2)。另外,在第一層迴圈中,由於step_003、step_004步驟的存在,則a*的每次尋路是隨時都有可能提前結束的。
今天博文暫且到此,後面再分享有關a*演算法的高階話題討論。
ACM演算法入門
oj上的一些水題 可用來練手和增加自信 poj3299,poj2159,poj2739,poj1083,poj2262,poj1503,poj3006,poj2255,poj3094 初期 一.基本演算法 1 列舉.poj1753,poj2965 2 貪心 poj1328,poj2109,poj25...
演算法入門(一)
1.for迴圈的使用 其實簡單的for 初始化 判斷條件 調整 迴圈,一般都會用。tip break用於跳出for迴圈,continue用於跳出此次迴圈,進入下一次 for 死迴圈 如 int i,j 3,n 5 for i 0 ij 迴圈結束時,i 4 q1.求1000 9999中的aabb型別的...
演算法入門 遞推
主要思想 通過已知的條件 已知結果 利用特定的關係,逐步遞推 順推 逆推 直到有解或者無解。主要分為兩種 順推,從已知條件出發,直至推出解。逆推,從已知結果出發 直至推出解。需要注意的 每一遞推結果,都是下一步遞推的條件。順推 斐波那契數列 f0 0,f1 1,fn f n 1 f n 2 n 2,...