ACM 啟發式搜尋

2021-08-30 17:50:48 字數 4128 閱讀 8594

開篇

這篇文章介紹找最短路徑的一種演算法,它的字我比較喜歡:啟發式搜尋。

這是用一般的搜素方法,類似窮舉的效果

下面的圖是用a*搜素的效果,也就是本文要介紹的演算法。

可以看出,用a*演算法減少了許多計算量,它的效率有了顯著的提高。

下面將為你解答上圖中的演算法是如何實現的。

正文

搜尋區域介紹

圖中左邊的綠色點是搜尋的起點a,目標點是右邊的紅色點b,中間被障礙物擋住(藍色部分)。

我們的目的是從起點出發,找到一條到達目標點的最短路徑。

把整個圖都分為乙個個小方塊只是為了這樣方便討論,更多的應用中,也可以把圖分為其它方塊的組合。

開始搜尋

目標是找出從a點出發到b的最短路徑,所以我們從a點開始搜尋,直到找到目標b。

搜尋的步驟是這樣的:

1、從起點a開始把a加入到openlist中。openlist解釋:它是乙個佇列,裡面元素是一些方塊,它們有可能構成最短路徑。現在佇列中只有元 素a,以後會加入更多的元素。以後會對裡的元素進行檢查,從裡面來找到構成最短路徑的元素。

2、看起點a周圍的元素是否可達(是否能從a到達它們)把從a可到達的元素加入到openlist中,並且加入到openlist中的節點維護乙個指指標,指向他的父親,也即a點。如果a周圍有障礙物就忽略它。從這個圖看, a周圍把個元素都可達,所以把它們都加到openlist中。

3、把起點a放入closelist中,在closelist中的點意味著以後不需要再去考慮它了。對於a節點,a可達的點都加入到了openlist中,以後也就不用考慮a的情況了。

經過以上三步操作後的效果圖如下所示

圖中被暗綠色包圍的就是openlist中的點,一共八個,都是從起點a可達的點,並且他們中的每個都有乙個指向他們父節點的指標(圖中的小針方向)被高亮綠色包圍的表示closelist中的點,可以看出起點a已經在closelist中。

路徑選擇

從起點出發 ,下一步可以走的點現在有八個,選取哪乙個作為下一步的點呢?正常的思維是選取乙個離目標值最進,且在這些點中離遠點最近的點。

本文的思路也是這樣的,文中用

f = g + h

表示,其中:

對於每個點,都有自己的g、h、f。

其中g表示從特定的點到起點的距離,h表示從該點到目標的估值,那麼f就是經過該點路徑的估值。

下面詳細介紹

g:從起點到特定節點的距離,也就是g的父節點加上從g的父節點到起點a的距離g。圖中是邊長為10的正方形塊,所以就是g的父節點的值g

加上10(上下左右相鄰)或者加上14(斜塊相鄰、也就是對角線的長度,本來是14.14、、為了方便計算這裡取近似值)

h:h能用很多方法得到估計值.這裡用到的方法稱為manhattan method,h的值就是從考慮的點通過水平和垂直移動達到目標點的移動步數乘10(正方形塊的邊長為10).注意只是水平和垂直移動,不走斜線。並且忽略圖中的障礙物。

插一句:

對於上圖中的點,他們的f、g、h的值在圖中都有標明。

f、h、g的位置在起點右邊的點中已經有標註,其他點的位置同理。

現在看起點右邊的點(也就是標有字母的點)g=10,因為在起點正左邊。h=30,水平移動三個格仔可以到目標點b。f=g+h=40

(為了方便描述,把選取的點成為點m)

1、檢查m周圍的點,在closelist中則忽略它,如果可達且不在openlist中,則加入openlist中,同理的維護乙個指向父節點的指正,同時計算加入點的f h g 值。

2、如果m周圍的點在openlist中,則看從起點a通過m到這類點的路徑是不是小於他們的g值,如果是則更新他們的g、f值(更新為小的)。如果不是則不做任何操作。

3、把m從openlist中移除,加入closelist中。

對openlist中f最小的點(也就是起點左邊的點)的處理效果如下圖所示:

m的右邊、右上、右下是障礙物,所以忽略他們。m的左邊點在closelist中,也不去管他,剩下的是m的上、下、左上、左下的點。他們已經在openlist中,所以看從起點通過m到他們的距離是不是小於他們的g值。通過判斷,都比他們的g值大,所以做任何操作。

可以看出,現在的closelist已有兩個元素了(高亮綠色包圍的塊)

下一步的操作和上面敘述的一樣,從openlist中找出f最小的,重複上的操作。從圖中可以看出,現在的openlist中f最小的有兩個,就是剛剛考慮的點的正上方和正下方,其實這裡選哪個都無所謂,只是人們習慣於選擇較晚加入到openlist中的元素,這裡選擇下方的點。

同理,處理效果如下圖所示:

下面簡單的說下處理過程:

暫且稱現在處理的點為n吧。

n上方  在closelist中,不考慮。

n左方 在openlist中,看從原點通過n到它的距離為14+10大於10,不做操作,跳到下一步

n的左下方,下方 加入openlist中,同時記錄f、g 、h的值還有指向父節點的指標。

n的右下方這裡看做「不可達的點」原因是這兩個點都處於障礙物的對角上,當然這只是一種人為的規定。也可以取消這條規定就把它加入到openlist中。這只是一種規定,不必深究。

處理的結果是closelist中現在有三個元素,用高亮的藍色標記,同樣的,openlist中的元素用暗綠色標記出。

重複上的步驟,每次從openlist中選取f最小的點加入closelist中,同時處理這個點周圍的元素。。

直到目標節點也被加入到closelist中停止。

處理的效果如下圖所示:

如果用心看、你也許已經發現了,在起點正下方兩個點的g值,沒錯,就是圖中用橢圓圈起來的點,之前的g=28,現在是20。這是在演算法進行的時候更新的,可能 是這其中的某一步,處理這個點的時候,發現了一條更短的路徑20,替換了原來的28。

到這裡,問題已經基本解決了,最後的任務就是得到這條路徑。

只要從目標點出發,沿著他們的父節點遍歷,直到起點。就得到了一條最短路徑。

如下圖所示

總結

現在你應該對a*演算法有乙個初步的認識了吧,總結下演算法的實現過程:

1、把起點加入到openlist中

2、重複以下步驟

a、從openlist中找出f最小的節點,並把它當做當前的操作節點

b、檢查當前點周圍的點,如果已經在openlist中看是否能通過當前點得到更小的g,如果能就更新那個點的g,f的值,如果在closelist中或者是障礙物(不可達)則忽略他們

c、把當前點從openlist中移除 ,加入closelist中

d、當目標點加入closelist中時停止

3、儲存路徑,從目標點出發,按照父節點指標遍歷,直到找到起點。

後記

其實啟發式搜尋就是對窮舉的一種優化,讓每次搜尋都更接近目標。這就要通過估值函式實現,對於這類問題,找到乙個估值函式是關鍵。

估值函式:從當前點出發到目標點的花費。其實從這個理念上說,好像和分支界限法有些類似,都是在窮舉的基礎上對搜素優化。

啟發式搜尋

啟發式搜尋 heuristically search 又稱為有資訊搜尋 informed search 它是利用問題擁有的啟發資訊來引導搜尋,達到減少搜尋範圍 降低問題複雜度的目的,這種利用啟發資訊的搜尋過程稱為啟發式搜尋。例題 八數碼問題 運用優先佇列,根據目前已經確定的位置算出目前的價值,並匯入...

啟發式搜尋

啟發式搜尋 啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置進行搜尋直到目標。這樣可以省略大量無謂的搜尋路徑,提高了效率。在啟發式搜尋中,對位置的估價是十分重要的。採用了不同的估價可以有不同的效果。在啟發式搜尋中,我們每次找到當前 最有希望是最短路徑 的狀態進...

A 演算法(啟發式搜尋)

a 演算法,a a star 演算法是一種靜態路網中求解最短路徑最有效的直接搜尋方法,也是解決許多搜尋問題的有效演算法。演算法中的距離估算值與實際值越接近,最終搜尋速度越快。別稱 啟發式搜尋 表示式 f n g n h n f n g n h n f n g n h n 公式表示為 f n g n ...