迷宮尋路問題——a*演算法
迷宮尋路問題是人工智慧中的有趣問題,如何表示狀態空間和搜尋路徑是尋路問題的重點,本文的主要內容是a*搜尋演算法的理解和應用,首先對基本知識和演算法思想進行了解,再通過其對迷宮問題求解應用,編寫 python 程式進行深入學習。
1. 搜尋區域
我們假設某個人要從 start 點到達 end 點,存在牆壁把這兩個點層層隔開,如下圖所示,綠色部分代表起點 start 和終點 end,紅色部分代表它們之間的牆:
我們把這一塊搜尋區域分成了乙個乙個的方格,使搜尋區域簡單化,這正是尋找路徑的第一步。這種方法將我們的搜尋區域簡化成了乙個普通的二維陣列。陣列中的每乙個元素表示對應的乙個方格,該方格的狀態被標記為可通過的和不可通過的。通過找出從 start 點到 end 點所經過的方格,就能得到 start->end 的路徑。
2. open 和 closed 表
建立了乙個簡單的搜尋區域後,a*演算法有兩個重要的資料列表:乙個記錄下所有被考慮來尋找最短路徑的方格(稱為 open列表)和乙個記錄下不會再被考慮的方格(稱為 closed列表)。
首先在 closed 列表中新增起點位置,然後把所有與它當前位置相鄰的可通行小方格新增到 open 列表中。在a*演算法中,我們從起點開始,依次檢查它的相鄰方格,選取相鄰方格然後繼續向外擴充套件直到找到目的地。但是該選哪乙個方格呢?我們需要乙個評價值。
3. 路徑評價
設定路徑上的每個方格對應乙個 評價值 f = g + h:
g 是從起點沿著已生成的路徑到乙個給定方格的移動開銷,從起點開始到相鄰方格的移動量為1,該值會隨著離始點越來越遠而增大。
h 是從當前方格到終點的移動估算值,被稱為視探,因為我們並不能確定剩餘移動開銷是多少,它僅僅是乙個估算值。移動量估算值離真實值越接近,最終的路徑會更加精確。如果估計值停止作用,很可能生成的路徑不會是最優的。
4. 演算法流程
重複以下步驟,直到遍歷到終點 end,找到最短路徑:
選取當前 open 列表中評價值 f 最小的節點,將這個節點稱為 s;
將 s 從 open 列表移除,然後新增 s 到 closed 列表中;
對於與 s 相鄰的每一塊可通行的方格節點 t:如果 t 在 closed 列表中,忽略;如果 t 不在 open 列表中,新增它然後計算出它的評價值 f;如果 t 已經在 open 列表中,當我們從 s 到達 t 時,檢查是否能得到 更小的 f 值,如果是,更新它的 f 值和它的前繼(parent = s)。
在此迷宮問題中,將使用 「曼哈頓距離」(也叫 「曼哈頓長」 或者 「城市街區距離」 )作為 h 值,計算出距離終點水平和垂直方向上的方格數量和,忽略障礙物。這裡 h 作為一種搜尋的啟發資訊,搜尋過程為廣度優先搜尋+貪心策略。當 end 被加入到 open 列表作為待檢驗節點時,表示路徑被找到,此時應終止迴圈;或者當 open 列表為空,表明已無可以新增的新節點,而已檢驗過的節點中沒有終點節點,則意味著無路徑可達終點,此時也終止迴圈。從終點開始沿父節點回溯到起點,記錄整個遍歷中得到的節點座標,便得到了最優路徑。
5. 演算法實現
輸入地圖:
基本的搜尋流程:
# 查詢路徑的入口函式
def find_path(self):
# 構建開始節點
p = node_elem(none, self.s_x, self.s_y, 0.0)
while true:
# 擴充套件節點
self.extend_round(p)
# 如果open表為空,則不存在路徑,返回
if not self.open:
return
# 取f值最小的節點
idx, p = self.get_best()
# 到達終點,生成路徑,返回
if self.is_target(p):
self.make_path(p)
return
# 把此節點加入close表,並從open表裡刪除
del self.open[idx]
選取 f 值最小的節點作為擴充套件節點,其中 g 是實際移動量,h 是估計剩餘移動量,我們取用曼哈頓距離:
# 求距離
def get_dist(self, i):
# f = g + h
return i.dist + math.sqrt((self.e_x-i.x)*(self.e_x-i.x))+ math.sqrt((self.e_y-i.y)*(self.e_y-i.y))
當我們遍歷到終點節點的時候,對路徑進行回溯,就能得到最優路徑:
# 生成路徑
def make_path(self, p):
# 從終點回溯到起點,起點的parent為none
while p:
p = p.parent
執行結果:
6. 總結
在本文的例項中,我們採用a*演算法得到了最終路徑,搜尋過程為啟發式廣度優先搜尋,節點擊擇上實質上為貪心演算法。
迷宮尋路(A星尋路演算法)
題目 假設我們有乙個7 5大小的迷宮,如下圖所示,綠色格仔表示起點,紅色的格仔表示終點,中間的3個深灰色格仔表示障礙物。請找到一條從起點到終點最短的路徑。解題思路 需要引入兩個集合和乙個公式,如下 具體步驟 把起點放入openlist 檢查openlist中是否有值,如果沒有則無法到達終點,結束尋路...
迷宮尋路(bfs)
第一次寫部落格,希望能把基礎的演算法記錄下來,以後快要忘記了可以拿來複習。題目 輸入輸出要求 樣例 輸入樣例 8 8 0 0 1 0 0 0 1 0 0 0 1 0 0 0 1 0 0 0 0 0 1 1 0 0 0 1 1 1 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 1...
Qt 迷宮自動尋路
標頭檔案 ifndef widget h define widget h include include include include include include include include include includeusing namespace std struct mypoint...