本文參考蘭大大佬scdn:無人駕駛汽車系統入門(十六)——最短路徑搜尋之a*演算法
適合兩文配合食用(只是對**的理解放在這裡)
首先先介紹bfs廣度優先演算法是如何找到最優路徑的:
下面是bfs的python偽**:意思就是我首先從起點開始得到鄰節點然後不斷的檢視沒有遍歷過的鄰節點直至遍歷結束。
def bfs(root)
q= //
while len(q)>0:
node=q.pop(0)//pop操作將list頭的元素彈出並且返回該彈出元素
print (node)
#將所有子節點入佇列
for i in node_child:
//——————————————————————修改演算法為機械人路徑尋找的演算法————————————//
frontier = queue()//建立乙個佇列(python中的list)
frontier.put(start)//將第乙個起點放入佇列
visited = {}//此字典用來記錄已經遍歷過的方格
visited[start] = true //起點是遍歷過的節點
while not frontier.empty()://直到所有的節點都遍歷完
current = frontier.get()//這裡應該是pop 遍歷結束之後將其彈出。
for next in graph.neighbors(current)://對每乙個鄰節點操作
if next not in visited://判斷鄰節點是否遍歷過
frontier.put(next)//沒有遍歷過就將其放入下面要遍歷的節點(frontier)中
visited[next] = true //標記已經遍歷
//——————————————————————修改演算法為可以回溯路徑的演算法————————————//
frontier = queue()
frontier.put(star)
came_from = {}
came_from[start] = none //存放的是其上乙個節點(這裡我們假設上個節點就是距離起始點最近的節點)
while not frontier.empty()://直到所有的節點都遍歷完
current = frontier.pop()//得到第乙個frontier並且彈出
for next in graph.neighbors(current)://對此frontier的鄰居節點判斷
if next not in came_from://如果鄰居節點不在之前遍歷過的節點
frontier.put(next)//那麼就將其放入frontier中之後去遍歷
//遍歷結束之後就可以得到最優路徑了
current = goal//從目的地觸發
path =
while current != start
current = came_from[current]
path.reverse()
但是我們的bfs就是簡單的窮舉,遍歷,如何更智慧型一點呢?
我們可以用上源節點和目的節點的位置資訊來引導最佳路徑的尋找,啟發式的尋找
//如何加入這個目的點和原點資訊來啟發路徑尋找呢?
//曼哈頓距離是度量兩點的一種距離,我們用曼哈頓距離的小大來表示距離目標點的進遠。
//所以所有的節點都有乙個目標級
frontier = priorityqueue()//因為我們有優先順序了,所以要用優先順序佇列,曼哈頓距離越小,優先順序越高
frontier.put(start, 0)
came_from = {}
came_from[start] = none
while not frontier.empty():
current = frontier.get()
if current == goal://一旦搜尋到目標(不管中間的路徑記錄是不是最佳)我就馬上停止遍歷
break
for next in graph.neighbors(current):
if next not in came_from:
priority = heuristic(goal, next)//計算優先順序(曼哈頓距離)
frontier.put(next, priority)
came_from[next] = current
哇,大功告成
在你沾沾自喜的時候,有一些問題就出現了
你發現你最後的結果有可能不是最優路徑,這個問題的出現個人認為有以下原因
1.搜尋到馬上停止不能很好的得到全域性的路徑資訊
2.基於距離的優先順序搜尋使得到最後到達目的節點中間遍歷的節點,沒有包含最優路徑(類似於slam中你沒有得到全域性地圖,你的路徑規劃也只能是貪心次優的)
3.在bfs中的確上乙個點是距離原點最近的,但是之後啟發式的演算法,不一定就可以使得上個點是最好的回到原點的方式。
所以按照原文中說的,我們加上迪傑斯特拉演算法:
迪傑斯特拉演算法偽**:
frontier = priorityqueue()
frontier.put(start, 0)
came_from = {}//記錄了某節點離源節點最近的路徑的父節點
cost_so_far = {}//記錄了某節點之前最近的父節點的cost(如果沒有遍歷過則為none)
came_from[start] = none
cost_so_far[start] = 0
while not frontier.empty():
current = frontier.get()
if current == goal:
break
for next in graph.neighbors(current):
new_cost = cost_so_far[current] + 1
if next not in cost_so_far or new_cost < cost_so_far[next]://如果「該節點的鄰節點」沒有遍歷過,或者說遍歷過並且之前的遍歷發現的路徑更遠(cost更大)
cost_so_far[next] = new_cost//則將此次路徑更新到下個節點
priority = new_cost//cost決定優先順序
frontier.put(next, priority)
came_from[next] = current
//————————————————————————————————a*——————————————————————————————//
//一方面,我們需要演算法有方向地進行擴散(啟發式),另一方面我們需要得到盡可能最短的路徑,因此a*就誕生了, 它結合了dijkstra和啟發式演算法的優點
frontier = priorityqueue()
frontier.put(start, 0)
came_from = {}
cost_so_far = {}
came_from[start] = none
cost_so_far[start] = 0
while not frontier.empty():
current = frontier.get()
if current == goal:
break
for next in graph.neighbors(current):
new_cost = cost_so_far[current] + 1
if next not in cost_so_far or new_cost < cost_so_far[next]:
cost_so_far[next] = new_cost
priority = new_cost + heuristic(goal, next)//兩種代價共同決定優先順序
frontier.put(next, priority)
came_from[next] = current
面試裝逼指南 一分鐘英語自我介紹
英語1min的selfintroduction其實不需要很好的美式發音,或者很完備的語法,其實最重要的是你說話是為了表達 你需要表達出自己想說的內容,下面有三個tip 說點面試官的做過的事情,或者面試官感興趣的事情 對於對方正在做或者感興趣的事情,發表自己的看法 說說你做過的和他們業務相關的事情,或...
JS實戰裝逼指南
嗯,就這樣決定了,不會python和js的程式設計師,不是好的ios工程師 本喵在2016年12月safari探索時,發現一頁殘缺的js秘笈,於是潛心研究,總結如下裝逼指南 若有相應的編碼規範,不影響可讀性,還是值得提倡的 findarticlebysearchingwhitelist functi...
python面試指南 Python面試指南
1 python基本語法 1 staticmethod 和 classmethod python中有三種方法,例項方法 類方法 classmethod 靜態方法 staticmethod 類方法的第乙個引數是cls,表示該類的乙個例項,靜態方法基本上和乙個全域性函式相同 class a object...