日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

启发式搜索A*算法

發(fā)布時(shí)間:2023/12/19 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 启发式搜索A*算法 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

A*?尋路算法

?(2011-02-15 10:53:11) 轉(zhuǎn)載
標(biāo)簽:?

游戲

分類:?算法

概述

雖然掌握了 A* 算法的人認(rèn)為它容易,但是對于初學(xué)者來說, A* 算法還是很復(fù)雜的。

搜索區(qū)域(The Search Area)

我們假設(shè)某人要從 A 點(diǎn)移動(dòng)到 B 點(diǎn),但是這兩點(diǎn)之間被一堵墻隔開。如圖 1 ,綠色是 A ,紅色是 B ,中間藍(lán)色是墻。

?

?

圖 1

你應(yīng)該注意到了,我們把要搜尋的區(qū)域劃分成了正方形的格子。這是尋路的第一步,簡化搜索區(qū)域,就像我們這里做的一樣。這個(gè)特殊的方法把我們的搜索區(qū)域簡化為了 2 維數(shù)組。數(shù)組的每一項(xiàng)代表一個(gè)格子,它的狀態(tài)就是可走 (walkalbe) 和不可走 (unwalkable) 。通過計(jì)算出從 A 到 B 需要走過哪些方格,就找到了路徑。一旦路徑找到了,人物便從一個(gè)方格的中心移動(dòng)到另一個(gè)方格的中心,直至到達(dá)目的地。

方格的中心點(diǎn)我們成為“節(jié)點(diǎn) (nodes) ”。如果你讀過其他關(guān)于 A* 尋路算法的文章,你會(huì)發(fā)現(xiàn)人們常常都在討論節(jié)點(diǎn)。為什么不直接描述為方格呢?因?yàn)槲覀冇锌赡馨阉阉鲄^(qū)域劃為為其他多變形而不是正方形,例如可以是六邊形,矩形,甚至可以是任意多變形。而節(jié)點(diǎn)可以放在任意多邊形里面,可以放在多變形的中心,也可以放在多邊形的邊上。我們使用這個(gè)系統(tǒng),因?yàn)樗詈唵巍?/p>

開始搜索(Starting the Search)

一旦我們把搜尋區(qū)域簡化為一組可以量化的節(jié)點(diǎn)后,就像上面做的一樣,我們下一步要做的便是查找最短路徑。在 A* 中,我們從起點(diǎn)開始,檢查其相鄰的方格,然后向四周擴(kuò)展,直至找到目標(biāo)。

我們這樣開始我們的尋路旅途:

1.???????從起點(diǎn) A 開始,并把它就加入到一個(gè)由方格組成的 open list( 開放列表 ) 中。這個(gè) open list 有點(diǎn)像是一個(gè)購物單。當(dāng)然現(xiàn)在 open list 里只有一項(xiàng),它就是起點(diǎn) A ,后面會(huì)慢慢加入更多的項(xiàng)。 Open list 里的格子是路徑可能會(huì)是沿途經(jīng)過的,也有可能不經(jīng)過。基本上 open list 是一個(gè)待檢查的方格列表。

2.???????查看與起點(diǎn) A 相鄰的方格 ( 忽略其中墻壁所占領(lǐng)的方格,河流所占領(lǐng)的方格及其他非法地形占領(lǐng)的方格 ) ,把其中可走的 (walkable) 或可到達(dá)的 (reachable) 方格也加入到 open list 中。把起點(diǎn) A 設(shè)置為這些方格的父親 (parent node 或 parent square) 。當(dāng)我們在追蹤路徑時(shí),這些父節(jié)點(diǎn)的內(nèi)容是很重要的。稍后解釋。

3.???????把 A 從 open list 中移除,加入到 close list( 封閉列表 ) 中, close list 中的每個(gè)方格都是現(xiàn)在不需要再關(guān)注的。

如下圖所示,深綠色的方格為起點(diǎn),它的外框是亮藍(lán)色,表示該方格被加入到了 close list 。與它相鄰的黑色方格是需要被檢查的,他們的外框是亮綠色。每個(gè)黑方格都有一個(gè)灰色的指針指向他們的父節(jié)點(diǎn),這里是起點(diǎn) A 。

?

圖 2 。

下一步,我們需要從 open list 中選一個(gè)與起點(diǎn) A 相鄰的方格,按下面描述的一樣或多或少的重復(fù)前面的步驟。但是到底選擇哪個(gè)方格好呢?具有最小 F 值的那個(gè)。

?

路徑排序(Path Sorting)

計(jì)算出組成路徑的方格的關(guān)鍵是下面這個(gè)等式:

F = G + H

這里,

G = 從起點(diǎn) A 移動(dòng)到指定方格的移動(dòng)代價(jià),沿著到達(dá)該方格而生成的路徑。

H = 從指定的方格移動(dòng)到終點(diǎn) B 的估算成本。這個(gè)通常被稱為試探法,有點(diǎn)讓人混淆。為什么這么叫呢,因?yàn)檫@是個(gè)猜測。直到我們找到了路徑我們才會(huì)知道真正的距離,因?yàn)橥局杏懈鞣N各樣的東西 ( 比如墻壁,水等 ) 。本教程將教你一種計(jì)算 H 的方法,你也可以在網(wǎng)上找到其他方法。

我們的路徑是這么產(chǎn)生的:反復(fù)遍歷 open list ,選擇 F 值最小的方格。這個(gè)過程稍后詳細(xì)描述。我們還是先看看怎么去計(jì)算上面的等式。

如上所述, G 是從起點(diǎn)A移動(dòng)到指定方格的移動(dòng)代價(jià)。在本例中,橫向和縱向的移動(dòng)代價(jià)為 10 ,對角線的移動(dòng)代價(jià)為 14 。之所以使用這些數(shù)據(jù),是因?yàn)閷?shí)際的對角移動(dòng)距離是 2 的平方根,或者是近似的 1.414 倍的橫向或縱向移動(dòng)代價(jià)。使用 10 和 14 就是為了簡單起見。比例是對的,我們避免了開放和小數(shù)的計(jì)算。這并不是我們沒有這個(gè)能力或是不喜歡數(shù)學(xué)。使用這些數(shù)字也可以使計(jì)算機(jī)更快。稍后你便會(huì)發(fā)現(xiàn),如果不使用這些技巧,尋路算法將很慢。

?

既然我們是沿著到達(dá)指定方格的路徑來計(jì)算 G 值,那么計(jì)算出該方格的 G 值的方法就是找出其父親的 G 值,然后按父親是直線方向還是斜線方向加上 10 或 14 。隨著我們離開起點(diǎn)而得到更多的方格,這個(gè)方法會(huì)變得更加明朗。

?

有很多方法可以估算 H 值。這里我們使用 Manhattan 方法,計(jì)算從當(dāng)前方格橫向或縱向移動(dòng)到達(dá)目標(biāo)所經(jīng)過的方格數(shù),忽略對角移動(dòng),然后把總數(shù)乘以 10 。之所以叫做 Manhattan 方法,是因?yàn)檫@很像統(tǒng)計(jì)從一個(gè)地點(diǎn)到另一個(gè)地點(diǎn)所穿過的街區(qū)數(shù),而你不能斜向穿過街區(qū)。重要的是,計(jì)算 H 是,要忽略路徑中的障礙物。這是對剩余距離的估算值,而不是實(shí)際值,因此才稱為試探法。

?

把 G 和 H 相加便得到 F 。我們第一步的結(jié)果如下圖所示。每個(gè)方格都標(biāo)上了 F , G , H 的值,就像起點(diǎn)右邊的方格那樣,左上角是 F ,左下角是 G ,右下角是 H 。

?

圖 3

好,現(xiàn)在讓我們看看其中的一些方格。在標(biāo)有字母的方格, G = 10 。這是因?yàn)樗椒较驈钠瘘c(diǎn)到那里只有一個(gè)方格的距離。與起點(diǎn)直接相鄰的上方,下方,左方的方格的 G 值都是 10 ,對角線的方格 G 值都是 14 。

?

H 值通過估算起點(diǎn)于終點(diǎn) ( 紅色方格 ) 的 Manhattan 距離得到,僅作橫向和縱向移動(dòng),并且忽略沿途的墻壁。使用這種方式,起點(diǎn)右邊的方格到終點(diǎn)有 3 個(gè)方格的距離,因此 H = 30 。這個(gè)方格上方的方格到終點(diǎn)有 4 個(gè)方格的距離 ( 注意只計(jì)算橫向和縱向距離 ) ,因此 H = 40 。對于其他的方格,你可以用同樣的方法知道 H 值是如何得來的。

?

每個(gè)方格的 F 值,再說一次,直接把 G 值和 H 值相加就可以了。

?

繼續(xù)搜索(Continuing the Search)

為了繼續(xù)搜索,我們從 open list 中選擇 F 值最小的 ( 方格 ) 節(jié)點(diǎn),然后對所選擇的方格作如下操作:

4.???????把它從 open list 里取出,放到 close list 中。

5.???????檢查所有與它相鄰的方格,忽略其中在 close list 中或是不可走 (unwalkable) 的方格 ( 比如墻,水,或是其他非法地形 ) ,如果方格不在 open lsit 中,則把它們加入到 open list 中。

把我們選定的方格設(shè)置為這些新加入的方格的父親。

6.???????如果某個(gè)相鄰的方格已經(jīng)在 open list 中,則檢查這條路徑是否更優(yōu),也就是說經(jīng)由當(dāng)前方格 ( 我們選中的方格 ) 到達(dá)那個(gè)方格是否具有更小的 G 值。如果沒有,不做任何操作。

相反,如果 G 值更小,則把那個(gè)方格的父親設(shè)為當(dāng)前方格 ( 我們選中的方格 ) ,然后重新計(jì)算那個(gè)方格的 F 值和 G 值。如果你還是很混淆,請參考下圖。

?

圖 4

Ok ,讓我們看看它是怎么工作的。在我們最初的 9 個(gè)方格中,還有 8 個(gè)在 open list 中,起點(diǎn)被放入了 close list 中。在這些方格中,起點(diǎn)右邊的格子的 F 值 40 最小,因此我們選擇這個(gè)方格作為下一個(gè)要處理的方格。它的外框用藍(lán)線打亮。

?

首先,我們把它從 open list 移到 close list 中 ( 這就是為什么用藍(lán)線打亮的原因了 ) 。然后我們檢查與它相鄰的方格。它右邊的方格是墻壁,我們忽略。它左邊的方格是起點(diǎn),在 close list 中,我們也忽略。其他 4 個(gè)相鄰的方格均在 open list 中,我們需要檢查經(jīng)由這個(gè)方格到達(dá)那里的路徑是否更好,使用 G 值來判定。讓我們看看上面的方格。它現(xiàn)在的 G 值為 14 。如果我們經(jīng)由當(dāng)前方格到達(dá)那里, G 值將會(huì)為 20( 其中 10 為到達(dá)當(dāng)前方格的 G 值,此外還要加上從當(dāng)前方格縱向移動(dòng)到上面方格的 G 值 10) 。顯然 20 比 14 大,因此這不是最優(yōu)的路徑。如果你看圖你就會(huì)明白。直接從起點(diǎn)沿對角線移動(dòng)到那個(gè)方格比先橫向移動(dòng)再縱向移動(dòng)要好。

?

當(dāng)把 4 個(gè)已經(jīng)在 open list 中的相鄰方格都檢查后,沒有發(fā)現(xiàn)經(jīng)由當(dāng)前方格的更好路徑,因此我們不做任何改變。現(xiàn)在我們已經(jīng)檢查了當(dāng)前方格的所有相鄰的方格,并也對他們作了處理,是時(shí)候選擇下一個(gè)待處理的方格了。

?

因此再次遍歷我們的 open list ,現(xiàn)在它只有 7 個(gè)方格了,我們需要選擇 F 值最小的那個(gè)。有趣的是,這次有兩個(gè)方格的 F 值都 54 ,選哪個(gè)呢?沒什么關(guān)系。從速度上考慮,選擇最后加入 open list 的方格更快。這導(dǎo)致了在尋路過程中,當(dāng)靠近目標(biāo)時(shí),優(yōu)先使用新找到的方格的偏好。但是這并不重要。 ( 對相同數(shù)據(jù)的不同對待,導(dǎo)致兩中版本的 A* 找到等長的不同路徑 ) 。

?

我們選擇起點(diǎn)右下方的方格,如下圖所示。

?

圖 5

?

這次,當(dāng)我們檢查相鄰的方格時(shí),我們發(fā)現(xiàn)它右邊的方格是墻,忽略之。上面的也一樣。

我們把墻下面的一格也忽略掉。為什么?因?yàn)槿绻淮┰綁堑脑?#xff0c;你不能直接從當(dāng)前方格移動(dòng)到那個(gè)方格。你需要先往下走,然后再移動(dòng)到那個(gè)方格,這樣來繞過墻角。 ( 注意:穿越墻角的規(guī)則是可選的,依賴于你的節(jié)點(diǎn)是怎么放置的 )

?

這樣還剩下 5 個(gè)相鄰的方格。當(dāng)前方格下面的 2 個(gè)方格還沒有加入 open list ,所以把它們加入,同時(shí)把當(dāng)前方格設(shè)為他們的父親。在剩下的 3 個(gè)方格中,有 2 個(gè)已經(jīng)在 close list 中 ( 一個(gè)是起點(diǎn),一個(gè)是當(dāng)前方格上面的方格,外框被加亮的 ) ,我們忽略它們。最后一個(gè)方格,也就是當(dāng)前方格左邊的方格,我們檢查經(jīng)由當(dāng)前方格到達(dá)那里是否具有更小的 G 值。沒有。因此我們準(zhǔn)備從 open list 中選擇下一個(gè)待處理的方格。

?

不斷重復(fù)這個(gè)過程,直到把終點(diǎn)也加入到了 open list 中,此時(shí)如下圖所示。

?

圖 6

?

注意,在起點(diǎn)下面 2 格的方格的父親已經(jīng)與前面不同了。之前它的 G 值是 28 并且指向它右上方的方格。現(xiàn)在它的 G 值為 20 ,并且指向它正上方的方格。這在尋路過程中的某處發(fā)生,使用新路徑時(shí) G 值經(jīng)過檢查并且變得更低,因此父節(jié)點(diǎn)被重新設(shè)置, G 和 F 值被重新計(jì)算。盡管這一變化在本例中并不重要,但是在很多場合中,這種變化會(huì)導(dǎo)致尋路結(jié)果的巨大變化。

?

那么我們怎么樣去確定實(shí)際路徑呢?很簡單,從終點(diǎn)開始,按著箭頭向父節(jié)點(diǎn)移動(dòng),這樣你就被帶回到了起點(diǎn),這就是你的路徑。如下圖所示。從起點(diǎn) A 移動(dòng)到終點(diǎn) B 就是簡單從路徑上的一個(gè)方格的中心移動(dòng)到另一個(gè)方格的中心,直至目標(biāo)。就是這么簡單!

?

圖 7

?

A*算法總結(jié)(Summary of the A* Method)

Ok ,現(xiàn)在你已經(jīng)看完了整個(gè)的介紹,現(xiàn)在我們把所有步驟放在一起:

1.?????????把起點(diǎn)加入 open list 。

2.?????????重復(fù)如下過程:

a.?????????遍歷 open list ,查找 F 值最小的節(jié)點(diǎn),把它作為當(dāng)前要處理的節(jié)點(diǎn)。

b.?????????把這個(gè)節(jié)點(diǎn)移到 close list 。

c.?????????對當(dāng)前方格的 8 個(gè)相鄰方格的每一個(gè)方格?

◆?????如果它是不可抵達(dá)的或者它在 close list 中,忽略它。否則,做如下操作。

◆?????如果它不在 open list 中,把它加入 open list ,并且把當(dāng)前方格設(shè)置為它的父親,記錄該方格的 F , G 和 H 值。

◆?????如果它已經(jīng)在 open list 中,檢查這條路徑 ( 即經(jīng)由當(dāng)前方格到達(dá)它那里 ) 是否更好,用 G 值作參考。更小的 G 值表示這是更好的路徑。如果是這樣,把它的父親設(shè)置為當(dāng)前方格,并重新計(jì)算它的 G 和 F 值。如果你的 open list 是按 F 值排序的話,改變后你可能需要重新排序。

d.?????????停止,當(dāng)你

◆?????把終點(diǎn)加入到了 open list 中,此時(shí)路徑已經(jīng)找到了,或者

◆?????查找終點(diǎn)失敗,并且 open list 是空的,此時(shí)沒有路徑。

3.?????????保存路徑。從終點(diǎn)開始,每個(gè)方格沿著父節(jié)點(diǎn)移動(dòng)直至起點(diǎn),這就是你的路徑。


?

啟發(fā)式搜索A*算法

?(2011-03-07 11:14:32) 轉(zhuǎn)載
標(biāo)簽:?

游戲

分類:?算法

據(jù) Drew 所知最短路經(jīng)算法現(xiàn)在重要的應(yīng)用有計(jì)算機(jī)網(wǎng)絡(luò)路由算法,機(jī)器人探路,交通路線導(dǎo)航,人工智能,游戲設(shè)計(jì)等等。美國火星探測器核心的尋路算法就是采用的D*(D Star)算法。

????最短路經(jīng)計(jì)算分靜態(tài)最短路計(jì)算和動(dòng)態(tài)最短路計(jì)算。

????靜態(tài)路徑最短路徑算法是外界環(huán)境不變,計(jì)算最短路徑。主要有Dijkstra算法,A*(A Star)算法。?

????動(dòng)態(tài)路徑最短路是外界環(huán)境不斷發(fā)生變化,即不能計(jì)算預(yù)測的情況下計(jì)算最短路。如在游戲中敵人或障礙物不斷移動(dòng)的情況下。典型的有D*算法。

這是Drew程序?qū)崿F(xiàn)的10000個(gè)節(jié)點(diǎn)的隨機(jī)路網(wǎng)三條互不相交最短路

真實(shí)路網(wǎng)計(jì)算K條路徑示例:節(jié)點(diǎn)5696到節(jié)點(diǎn)3006,三條最快速路,可以看出路徑基本上走環(huán)線或主干路。黑線為第一條,蘭線為第二條,紅線為第三條。約束條件系數(shù)為1.2。共享部分路段。顯示計(jì)算部分完全由Drew自己開發(fā)的程序完成。 

??參見?K條路算法測試程序

Dijkstra算法求最短路徑:

Dijkstra算法是典型最短路算法,用于計(jì)算一個(gè)節(jié)點(diǎn)到其他所有節(jié)點(diǎn)的最短路徑。主要特點(diǎn)是以起始點(diǎn)為中心向外層層擴(kuò)展,直到擴(kuò)展到終點(diǎn)為止。Dijkstra算法能得出最短路徑的最優(yōu)解,但由于它遍歷計(jì)算的節(jié)點(diǎn)很多,所以效率低。

Dijkstra算法是很有代表性的最短路算法,在很多專業(yè)課程中都作為基本內(nèi)容有詳細(xì)的介紹,如數(shù)據(jù)結(jié)構(gòu),圖論,運(yùn)籌學(xué)等等。

Dijkstra一般的表述通常有兩種方式,一種用永久和臨時(shí)標(biāo)號(hào)方式,一種是用OPEN, CLOSE表方式,Drew為了和下面要介紹的 A* 算法和 D* 算法表述一致,這里均采用OPEN,CLOSE表的方式。

大概過程:
創(chuàng)建兩個(gè)表,OPEN, CLOSE。
OPEN表保存所有已生成而未考察的節(jié)點(diǎn),CLOSED表中記錄已訪問過的節(jié)點(diǎn)。
1. 訪問路網(wǎng)中里起始點(diǎn)最近且沒有被檢查過的點(diǎn),把這個(gè)點(diǎn)放入OPEN組中等待檢查。
2. 從OPEN表中找出距起始點(diǎn)最近的點(diǎn),找出這個(gè)點(diǎn)的所有子節(jié)點(diǎn),把這個(gè)點(diǎn)放到CLOSE表中。
3. 遍歷考察這個(gè)點(diǎn)的子節(jié)點(diǎn)。求出這些子節(jié)點(diǎn)距起始點(diǎn)的距離值,放子節(jié)點(diǎn)到OPEN表中。
4. 重復(fù)2,3,步。直到OPEN表為空,或找到目標(biāo)點(diǎn)。

這是在drew 程序中4000個(gè)節(jié)點(diǎn)的隨機(jī)路網(wǎng)上Dijkstra算法搜索最短路的演示,黑色圓圈表示經(jīng)過遍歷計(jì)算過的點(diǎn)由圖中可以看到Dijkstra算法從起始點(diǎn)開始向周圍層層計(jì)算擴(kuò)展,在計(jì)算大量節(jié)點(diǎn)后,到達(dá)目標(biāo)點(diǎn)。所以速度慢效率低。

提高Dijkstra搜索速度的方法很多,據(jù)Drew所知,常用的有數(shù)據(jù)結(jié)構(gòu)采用Binary heap的方法,和用Dijkstra從起始點(diǎn)和終點(diǎn)同時(shí)搜索的方法。

推薦網(wǎng)頁:http://www.cs.ecnu.edu.cn/assist/js04/ZJS045/ZJS04505/zjs045050a.htm

簡明扼要介紹Dijkstra算法,有圖解顯示和源碼下載。

A*(A Star)算法:啟發(fā)式(heuristic)算法

A*(A-Star)算法是一種靜態(tài)路網(wǎng)中求解最短路最有效的方法。

公式表示為:????????f(n)=g(n)+h(n),?
其中f(n) 是節(jié)點(diǎn)n從初始點(diǎn)到目標(biāo)點(diǎn)的估價(jià)函數(shù),
g(n) 是在狀態(tài)空間中從初始節(jié)點(diǎn)到n節(jié)點(diǎn)的實(shí)際代價(jià),
h(n)是從n到目標(biāo)節(jié)點(diǎn)最佳路徑的估計(jì)代價(jià)。

保證找到最短路徑(最優(yōu)解的)條件,關(guān)鍵在于估價(jià)函數(shù)h(n)的選取:
估價(jià)值h(n)<= n到目標(biāo)節(jié)點(diǎn)的距離實(shí)際值,這種情況下,搜索的點(diǎn)數(shù)多,搜索范圍大,效率低。但能得到最優(yōu)解。
如果 估價(jià)值>實(shí)際值, 搜索的點(diǎn)數(shù)少,搜索范圍小,效率高,但不能保證得到最優(yōu)解。
估價(jià)值與實(shí)際值越接近,估價(jià)函數(shù)取得就越好。
例如對于幾何路網(wǎng)來說,可以取兩節(jié)點(diǎn)間歐幾理德距離(直線距離)做為估價(jià)值,即f=g(n)+sqrt((dx-nx)*(dx-nx)+(dy-ny)*(dy-ny));這樣估價(jià)函數(shù)f在g值一定的情況下,會(huì)或多或少的受估價(jià)值h的制約,節(jié)點(diǎn)距目標(biāo)點(diǎn)近,h值小,f值相對就小,能保證最短路的搜索向終點(diǎn)的方向進(jìn)行。明顯優(yōu)于Dijstra算法的毫無無方向的向四周搜索。

conditions of heuristic
Optimistic (must be less than or equal to the real cost)
As close to the real cost as possible

主要搜索過程:
創(chuàng)建兩個(gè)表,OPEN表保存所有已生成而未考察的節(jié)點(diǎn),CLOSED表中記錄已訪問過的節(jié)點(diǎn)。
遍歷當(dāng)前節(jié)點(diǎn)的各個(gè)節(jié)點(diǎn),將n節(jié)點(diǎn)放入CLOSE中,取n節(jié)點(diǎn)的子節(jié)點(diǎn)X,->算X的估價(jià)值->
While(OPEN!=NULL)
{
從OPEN表中取估價(jià)值f最小的節(jié)點(diǎn)n;
if(n節(jié)點(diǎn)==目標(biāo)節(jié)點(diǎn)) break;
else
{
if(X in OPEN) 比較兩個(gè)X的估價(jià)值f //注意是同一個(gè)節(jié)點(diǎn)的兩個(gè)不同路徑的估價(jià)值
if( X的估價(jià)值小于OPEN表的估價(jià)值 )
   更新OPEN表中的估價(jià)值; //取最小路徑的估價(jià)值

if(X in CLOSE) 比較兩個(gè)X的估價(jià)值 //注意是同一個(gè)節(jié)點(diǎn)的兩個(gè)不同路徑的估價(jià)值
if( X的估價(jià)值小于CLOSE表的估價(jià)值 )
   更新CLOSE表中的估價(jià)值; 把X節(jié)點(diǎn)放入OPEN //取最小路徑的估價(jià)值

if(X not in both)
求X的估價(jià)值;
   并將X插入OPEN表中; //還沒有排序
}

將n節(jié)點(diǎn)插入CLOSE表中;
按照估價(jià)值將OPEN表中的節(jié)點(diǎn)排序; //實(shí)際上是比較OPEN表內(nèi)節(jié)點(diǎn)f的大小,從最小路徑的節(jié)點(diǎn)向下進(jìn)行。
}

?

上圖是和上面Dijkstra算法使用同一個(gè)路網(wǎng),相同的起點(diǎn)終點(diǎn),用A*算法的情況,計(jì)算的點(diǎn)數(shù)從起始點(diǎn)逐漸向目標(biāo)點(diǎn)方向擴(kuò)展,計(jì)算的節(jié)點(diǎn)數(shù)量明顯比Dijkstra少得多,效率很高,且能得到最優(yōu)解。

A*算法和Dijistra算法的區(qū)別在于有無估價(jià)值,Dijistra算法相當(dāng)于A*算法中估價(jià)值為0的情況。

 

推薦文章鏈接:

Amit?斯坦福大學(xué)一個(gè)博士的游戲網(wǎng)站,上面有關(guān)于A*算法介紹和不少有價(jià)值的鏈接????http://theory.stanford.edu/~amitp/GameProgramming/

Sunway寫的兩篇很好的介紹啟發(fā)式和A*算法的中文文章并有A*源碼下載:

初識(shí)A*算法?http://creativesoft.home.shangdu.net/AStart1.htm

深入A*算法?http://creativesoft.home.shangdu.net/AStart2.htm

需要注意的是Sunway上面文章“深入A*算法”中引用了一個(gè)A*的游戲程序進(jìn)行講解,并有這個(gè)源碼的下載,不過它有一個(gè)不小的Bug, 就是新的子節(jié)點(diǎn)放入OPEN表中進(jìn)行了排序,而當(dāng)子節(jié)點(diǎn)在Open表和Closed表中時(shí),重新計(jì)算估價(jià)值后,沒有重新的對Open表中的節(jié)點(diǎn)排序,這個(gè)問題會(huì)導(dǎo)致計(jì)算有時(shí)得不到最優(yōu)解,另外在路網(wǎng)權(quán)重懸殊很大時(shí),搜索范圍不但超過Dijkstra,甚至搜索全部路網(wǎng), 使效率大大降低。?

Drew 對這個(gè)問題進(jìn)行了如下修正,當(dāng)子節(jié)點(diǎn)在Open表和Closed表中時(shí),重新計(jì)算估價(jià)值后,刪除OPEN表中的老的節(jié)點(diǎn),將有新估價(jià)值的節(jié)點(diǎn)插入OPEN表中,重新排序,經(jīng)測試效果良好,修改的代碼如下,紅色部分為Drew添加的代碼.添加進(jìn)程序的相應(yīng)部分即可。

在函數(shù)GenerateSucc()中?
...................................
g=BestNode->g+1;
TileNumS=TileNum((int)x,(int)y);
if ((Old=CheckOPEN(TileNumS)) != NULL)?
{?
for(c=0;c<8;c++)
if(BestNode->Child[c] == NULL)
break;
BestNode->Child[c]=Old;

if (g < Old->g)?
{
Old->Parent=BestNode;
Old->g=g;
Old->f=g+Old->h;


//Drew 在該處添加如下紅色代碼?
//Implement by Drew?
NODE *q,*p=OPEN->NextNode, *temp=OPEN->NextNode;
while(p!=NULL && p->NodeNum != Old->NodeNum)
{
????q=p;
????p=p->NextNode;
}
if(p->NodeNum == Old->NodeNum)
{
???if(p==OPEN->NextNode)
??{
?????temp = temp->NextNode;
?????OPEN ->NextNode = temp;
??}
??else
??q->NextNode = p->NextNode;
?}
Insert(Old); // Insert Successor on OPEN list wrt f?
}?
......................................................?

 

另一種A*(A Star)算法:

這種算法可以不直接用估價(jià)值,直接用Dijkstra算法程序?qū)崿F(xiàn)A*算法,Drew對它進(jìn)行了測試,達(dá)到和A*完全一樣的計(jì)算效果,且非常簡單。

以鄰接矩陣為例,更改原來鄰接矩陣i行j列元素Dij為 Dij+Djq-Diq; 起始點(diǎn)到目標(biāo)點(diǎn)的方向i->j, 終點(diǎn)q. Dij為(i到j(luò)路段的權(quán)重或距離)

其中:Djq,Diq的作用相當(dāng)于估價(jià)值 Djq=(j到q的直線距離);Diq=(i到q的直線距離)

原理:i 到q方向符合Dij+Djq > Diq ,取Dij+Djq-Diq 小,如果是相反方向Dij+Djq-Diq會(huì)很大。因此達(dá)到向目標(biāo)方向?qū)ぢ返淖饔谩?/p>

 

動(dòng)態(tài)路網(wǎng),最短路徑算法 D*

A* 在靜態(tài)路網(wǎng)中非常有效(very efficient for static worlds),但不適于在動(dòng)態(tài)路網(wǎng),環(huán)境如權(quán)重等不斷變化的動(dòng)態(tài)環(huán)境下。?

D*是動(dòng)態(tài)A*(D-Star,Dynamic A Star)卡內(nèi)及梅隆機(jī)器人中心的Stentz在1994和1995年兩篇文章提出,主要用于機(jī)器人探路。是火星探測器采用的尋路算法。

Optimal and Efficient Path Planning for Partially-Known Environments

The Focussed D* Algorithm for Real-Time Replanning


主要方法(這些完全是Drew在讀了上述資料和編制程序中的個(gè)人理解,不能保證完全正確,僅供參考):

1.先用Dijstra算法從目標(biāo)節(jié)點(diǎn)G向起始節(jié)點(diǎn)搜索。儲(chǔ)存路網(wǎng)中目標(biāo)點(diǎn)到各個(gè)節(jié)點(diǎn)的最短路和該位置到目標(biāo)點(diǎn)的實(shí)際值h,k(k為所有變化h之中最小的值,當(dāng)前為k=h。每個(gè)節(jié)點(diǎn)包含上一節(jié)點(diǎn)到目標(biāo)點(diǎn)的最短路信息1(2),2(5),5(4),4(7)。則1到4的最短路為1-2-5-4。
原OPEN和CLOSE中節(jié)點(diǎn)信息保存。

2.機(jī)器人沿最短路開始移動(dòng),在移動(dòng)的下一節(jié)點(diǎn)沒有變化時(shí),無需計(jì)算,利用上一步Dijstra計(jì)算出的最短路信息從出發(fā)點(diǎn)向后追述即可,當(dāng)在Y點(diǎn)探測到下一節(jié)點(diǎn)X狀態(tài)發(fā)生改變,如堵塞。機(jī)器人首先調(diào)整自己在當(dāng)前位置Y到目標(biāo)點(diǎn)G的實(shí)際值h(Y),h(Y)=X到Y(jié)的新權(quán)值c(X,Y)+X的原實(shí)際值h(X).X為下一節(jié)點(diǎn)(到目標(biāo)點(diǎn)方向Y->X->G),Y是當(dāng)前點(diǎn)。k值取h值變化前后的最小。

3.用A*或其它算法計(jì)算,這里假設(shè)用A*算法,遍歷Y的子節(jié)點(diǎn),點(diǎn)放入CLOSE,調(diào)整Y的子節(jié)點(diǎn)a的h值,h(a)=h(Y)+Y到子節(jié)點(diǎn)a的權(quán)重C(Y,a),比較a點(diǎn)是否存在于OPEN和CLOSE中,方法如下:

while()
{
從OPEN表中取k值最小的節(jié)點(diǎn)Y;
遍歷Y的子節(jié)點(diǎn)a,計(jì)算a的h值 h(a)=h(Y)+Y到子節(jié)點(diǎn)a的權(quán)重C(Y,a)
{
????if(a in OPEN)?????比較兩個(gè)a的h值?
????if( a的h值小于OPEN表a的h值 )
????{
     更新OPEN表中a的h值;k值取最小的h值
??????????有未受影響的最短路經(jīng)存在
??????????break;?
????}
????if(a in CLOSE) 比較兩個(gè)a的h值 //注意是同一個(gè)節(jié)點(diǎn)的兩個(gè)不同路徑的估價(jià)值
????if( a的h值小于CLOSE表的h值 )
????{
     更新CLOSE表中a的h值; k值取最小的h值;將a節(jié)點(diǎn)放入OPEN表
??????????有未受影響的最短路經(jīng)存在
??????????break;
????}
????if(a not in both)
????????將a插入OPEN表中; //還沒有排序
}
放Y到CLOSE表;
OPEN表比較k值大小進(jìn)行排序;
}
機(jī)器人利用第一步Dijstra計(jì)算出的最短路信息從a點(diǎn)到目標(biāo)點(diǎn)的最短路經(jīng)進(jìn)行。

D*算法在動(dòng)態(tài)環(huán)境中尋路非常有效,向目標(biāo)點(diǎn)移動(dòng)中,只檢查最短路徑上下一節(jié)點(diǎn)或臨近節(jié)點(diǎn)的變化情況,如機(jī)器人尋路等情況。對于距離遠(yuǎn)的最短路徑上發(fā)生的變化,則感覺不太適用。?



上圖是Drew在4000個(gè)節(jié)點(diǎn)的隨機(jī)路網(wǎng)上做的分析演示,細(xì)黑線為第一次計(jì)算出的最短路,紅點(diǎn)部分為路徑上發(fā)生變化的堵塞點(diǎn),當(dāng)機(jī)器人位于982點(diǎn)時(shí),檢測到前面發(fā)生路段堵塞,在該點(diǎn)重新根據(jù)新的信息計(jì)算路徑,可以看到圓圈點(diǎn)為重新計(jì)算遍歷過的點(diǎn),僅僅計(jì)算了很少得點(diǎn)就找到了最短路,說明計(jì)算非常有效,迅速。綠線為計(jì)算出的繞開堵塞部分的新的最短路徑。

總結(jié)

以上是生活随笔為你收集整理的启发式搜索A*算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。