AStar 算法 1

原理

AStar 使用 F = G + H 來(lái)評(píng)估一個(gè)節(jié)點(diǎn)。
其中 G 代表起始節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)的代價(jià),H 代表目的節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)的代價(jià)。這樣,從起始節(jié)點(diǎn)開(kāi)始,不斷的尋找鄰居節(jié)點(diǎn)中 F 最小的,直到檢測(cè)到目的節(jié)點(diǎn)從而找到路徑為止。
下面是算法流程圖:

流程圖.png
  1. AStar 維護(hù)著一個(gè)開(kāi)放列表和一個(gè)封閉列表。開(kāi)放列表中存放著待檢查 F 值的節(jié)點(diǎn),每次主循環(huán)中都從 openList 中尋找 F 值最小的節(jié)點(diǎn)作為當(dāng)前節(jié)點(diǎn),然后將當(dāng)前節(jié)點(diǎn)的鄰居節(jié)點(diǎn)加入到 openList 中作為待檢查節(jié)點(diǎn)。封閉列表存放著不再檢查的節(jié)點(diǎn),每當(dāng)選出一個(gè)當(dāng)前節(jié)點(diǎn)之后意味著它的鄰居節(jié)點(diǎn)將要或已經(jīng)加入到開(kāi)放列表中,這個(gè)當(dāng)前節(jié)點(diǎn)便成為了一個(gè)不再檢查的節(jié)點(diǎn),所以要把它加入到 closeList 中,防止再次檢查。
  2. 在鄰居節(jié)點(diǎn)循環(huán)中如果這個(gè)鄰居節(jié)點(diǎn)不在 openList 中,那就需要設(shè)置 F、G、H 和 parentNode 并加入到 openList 中備選。
  3. 在鄰居節(jié)點(diǎn)循環(huán)中如果這個(gè)節(jié)點(diǎn)已經(jīng)在 openList 中,說(shuō)明它之前已經(jīng)作為鄰居節(jié)點(diǎn)加入到了 openList 中,但是沒(méi)有被選為當(dāng)前節(jié)點(diǎn)(因?yàn)樗?F 不是最小的)。而此時(shí)它又成為了另一個(gè)節(jié)點(diǎn)的鄰居節(jié)點(diǎn),如果經(jīng)由當(dāng)前節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)的 F 值變小了那就更新這個(gè)鄰居節(jié)點(diǎn)的數(shù)據(jù),否則什么也不做。
  4. openList 為空說(shuō)明搜索了所有地圖而沒(méi)有找到路徑。
  5. 當(dāng)前節(jié)點(diǎn)為目的節(jié)點(diǎn)說(shuō)明路徑已經(jīng)找到,沿著當(dāng)前節(jié)點(diǎn)的 parentNode 回溯就可以得到路徑數(shù)據(jù)。

G 和 H

AStar 依據(jù) G 和 H 值來(lái)評(píng)估一個(gè)節(jié)點(diǎn)在本次尋路過(guò)程中的代價(jià)。

這兩個(gè)值將經(jīng)由這個(gè)節(jié)點(diǎn)的路徑的代價(jià)分割成兩部分:

  1. 一部分是由起始節(jié)點(diǎn)到這個(gè)節(jié)點(diǎn)的代價(jià) G ,因?yàn)槁窂降乃阉鬟^(guò)程是從起始節(jié)點(diǎn)開(kāi)始循環(huán)的檢查當(dāng)前節(jié)點(diǎn)的每個(gè)鄰居節(jié)點(diǎn),所以這個(gè)值是確定的。
  2. 另一部分 F 是這個(gè)節(jié)點(diǎn)到目的節(jié)點(diǎn)的代價(jià),這個(gè)值一般是一個(gè)估計(jì)值(也可以是精確的)。這樣,因?yàn)橛?H 值影響著 F 的大小,路徑的搜索會(huì)有一個(gè)大概的方向,即 H 值會(huì)不斷的把搜索方向?qū)蚰康墓?jié)點(diǎn)的方向,這也是為什么 AStar 會(huì)更快,因?yàn)?H 值減少了算法檢查的節(jié)點(diǎn)個(gè)數(shù)。

下面用幾張截圖來(lái)說(shuō)明這兩個(gè)值的作用。
如下圖,現(xiàn)在有這樣一個(gè)地圖,先不考慮地圖中有其它山啊水啊不可達(dá)的區(qū)域,假設(shè)地圖上任何一個(gè)節(jié)點(diǎn)都是可達(dá)的,現(xiàn)在要在兩個(gè)圓點(diǎn)標(biāo)記的節(jié)點(diǎn)中尋找一條路徑。


屏幕快照 2016-02-19 22.09.32.png

首先是使用了“曼哈頓”方法計(jì)算 H 值的 AStar 結(jié)果,圖中藍(lán)色的節(jié)點(diǎn)是算法過(guò)程中被加入到了 openList 中的節(jié)點(diǎn),可以看到這個(gè)搜索過(guò)程沒(méi)有檢查過(guò)多的節(jié)點(diǎn),從一開(kāi)始就向著目的節(jié)點(diǎn)的方向搜索過(guò)去。

屏幕快照 2016-02-19 22.09.45.png

下面,把每個(gè) H 值的節(jié)點(diǎn)都置 0,也就是說(shuō)完全消除 H 值對(duì)算法的影響,根據(jù)原理大概可以預(yù)測(cè)到搜索過(guò)程會(huì)以起始節(jié)點(diǎn)為圓心,不斷的向外擴(kuò)展,直到到達(dá)了目的節(jié)點(diǎn)為止。下面是截圖:

屏幕快照 2016-02-19 22.22.16.png

G 讓算法找到更好的路徑,而 H 讓算法更快的找到路徑。

G 和 H 的單位問(wèn)題

因?yàn)?F 是由 G 和 H 相加得來(lái)的,所以二者的度量應(yīng)該是統(tǒng)一的。如果二者的度量不統(tǒng)一就會(huì)使二者中的一個(gè)值在節(jié)點(diǎn)評(píng)估中起主導(dǎo)作用,而另一個(gè)值變得失效了。比如再看使用了“曼哈頓”方法計(jì)算 H 值的 AStar ,這次把 H 值縮小十倍,算法檢查了更多的節(jié)點(diǎn),從而速度會(huì)變慢。截圖:

屏幕快照 2016-02-19 22.27.11.png

計(jì)算 H 的幾種常用方法

精確的 H 值

可以在路徑搜索之前預(yù)先計(jì)算任意兩個(gè)節(jié)點(diǎn)之間的代價(jià),然后在計(jì)算 H 值的時(shí)候直接查找這個(gè)值。但是這個(gè)方法在實(shí)際中不太現(xiàn)實(shí),因?yàn)樵诖蠖鄶?shù)游戲中一般地圖比較大、節(jié)點(diǎn)多(預(yù)計(jì)算的數(shù)據(jù)會(huì)很多)、存在著未知區(qū)域(無(wú)法預(yù)先計(jì)算)、地圖上還存在著其它的移動(dòng)目標(biāo)。這些因素都會(huì)使得這種精確 H 值的方法不是那么容易實(shí)現(xiàn)。

近似精確的 H 值

在地圖上均勻的設(shè)置一些導(dǎo)航點(diǎn),預(yù)先計(jì)算任意兩個(gè)導(dǎo)航點(diǎn)的代價(jià)。尋路過(guò)程中,當(dāng)要計(jì)算 H 值的時(shí)候,先尋找距離當(dāng)前節(jié)點(diǎn)最近的導(dǎo)航點(diǎn) w1 和距離目的節(jié)點(diǎn)最近的導(dǎo)航點(diǎn) w2 ,這樣 H 值就變成了一下這種形式:

H = h(當(dāng)前節(jié)點(diǎn), w1) + h(目的節(jié)點(diǎn), w2) + distance(w1, w2)

曼哈頓方法

設(shè)當(dāng)前節(jié)點(diǎn): n(column, row) ,目的節(jié)點(diǎn) t(column, row)

HManhattan(n) = D * [abs(n.column - t.column) + abs(n.row - t.row)]

(其中 D 是為了平衡 G 和 H 的度量)

對(duì)角線(xiàn)方法

設(shè)當(dāng)前節(jié)點(diǎn): n(column, row) ,目的節(jié)點(diǎn) t(column, row)

Diagonal.png

如上圖,路徑可以先沿對(duì)角線(xiàn)方向走向中間節(jié)點(diǎn) x,再沿直線(xiàn)走向目的節(jié)點(diǎn) t。
首先,對(duì)角線(xiàn)的代價(jià)為

Hd = Dd * [min(abs(n.column - t.column), abs(n.row - c.row))]

直線(xiàn)的代價(jià)為:

Hs = Ds * [max(abs(n.column - t.column), abs(n.row - c.row)) - min(abs(n.column - t.column), abs(n.row - c.row))]

H = Hd + Hs

歐幾里得和平方歐幾里德方法

設(shè)當(dāng)前節(jié)點(diǎn): n(column, row) ,目的節(jié)點(diǎn) t(column, row)

H = D * sqrt((n.column - t.column)(n.column - t.column) + (n.row - t.row)(n.row - t.row))

計(jì)算機(jī)計(jì)算平方根比較耗時(shí)間,考慮把開(kāi)平方的過(guò)程去掉,但是這樣會(huì)導(dǎo)致 G 和 H 的度量不同。

以上就是 AStar 的一些基本概念,最后來(lái)一個(gè)思維導(dǎo)圖吧:

AStar_mindnode.png

本文主要的代碼和資源文件在這里可以找到:https://github.com/Jiajiaju/AStar

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀(guān)點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1 序 2016年6月25日夜,帝都,天下著大雨,拖著行李箱和同學(xué)在校門(mén)口照了最后一張合照,搬離寢室打車(chē)去了提前租...
    RichardJieChen閱讀 5,152評(píng)論 0 12
  • 1基本安裝1.1在基于RHEL的系統(tǒng)中安裝Cassandra1.1.1必要條件? YUM包管理器? Root或...
    戰(zhàn)神湯姆閱讀 1,068評(píng)論 0 4
  • 清木走到窗前看著這座沉睡的城市有點(diǎn)陌生。一直以來(lái)他只顧著看腳下的路想念著那個(gè)人,從來(lái)沒(méi)有認(rèn)真地看著為之打拼的城市。...
    大Amo閱讀 202評(píng)論 0 0
  • 她被這個(gè)考古隊(duì)從地下挖出來(lái)時(shí),已是兩千多年之后了。她身上貼滿(mǎn)了塵土和污垢,與一塊破磚爛瓦沒(méi)什么區(qū)別。一個(gè)被招募來(lái)的...
    史文泓閱讀 329評(píng)論 0 0
  • 它是以色列作家埃特加·凱雷特寫(xiě)的一本隨筆集或叫散文集,2016年還有3天就要say goodbye了,這是...
    楊瓊的簡(jiǎn)書(shū)閱讀 278評(píng)論 0 0