1. 程式人生 > >廣度優先和深度優先和貪心法和Dijkstra和A*演算法的總結

廣度優先和深度優先和貪心法和Dijkstra和A*演算法的總結

廣度優先總結

1.在各個方向上都有同樣的探索。

對於一個圖他的廣度優先遍歷的步驟:
 1.利用佇列實現
 2.從源節點開始依次按照寬度進佇列,然後彈出
 3.每彈出一個節點,就把該節點所有沒有進過佇列的鄰接點放入佇列
 4.直到佇列變空

frontier = Queue()
frontier.put(start )
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:
         frontier.put(next)
         came_from[next] = current


深度優先總結

1.在各個方向上都有同樣權重的探索。遍歷的順序不一樣

針對一個圖的他深度優先遍歷的步驟:
1.利用棧實現
2.從源節點開始把節點按照深度放入棧,然後彈出
3.每彈出一個點,把該節點下一個沒有進過棧的鄰接點放入棧
4.直到棧變空

Dijkstra總結:

1.考慮到成本,對於路徑搜尋,走不同的路徑他花的成本是不一樣的。

2.我們新增一個新的變數跟蹤從開始位置的總移動成本。我們想在決定如何評估地點時考慮到移動成本;讓我們將佇列轉換為優先佇列。我們可能會多次訪問一個位置,如果成本變小了就更新字典邏輯。

3.從起始點開始在森林中緩慢地擴張

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] + graph.cost(current, next)
      if next not in cost_so_far or new_cost < cost_so_far[next]:
         cost_so_far[next] = new_cost
         priority = new_cost
         frontier.put(next, priority)
         came_from[next] = current


貪心法總結:

貪心演算法是指在對問題求解時,比如路徑尋找,總是做出在當前看來是最好的選擇。也就是說,不從整體最優上加以考慮,只做出在某種意義上的區域性最優解。是一種啟發式的方法

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

A*總結:

Dijkstra和貪心演算法的缺點:

1.Dijkstra演算法很好地找到了最短路徑,但它浪費了時間去探索那些沒有前途的方向。

2.貪婪的最好的第一次搜尋在有希望的方向上探索,但它可能找不到最短的路徑。

A*的做法:

A*演算法結合了這兩種方法,演算法使用從開始的實際距離和估計的距離到目標的距離。

演算法:Dijkstra演算法計算出起點的距離。貪婪的第一次搜尋估計到目標點的距離。A是用這兩個距離的和。

在不同的地方開了一個洞。你會發現,當貪婪的最好的第一次搜尋找到正確答案時,你也會發現它,探索同一領域。當貪婪的第一次搜尋找到了錯誤的答案(較長的路徑)時,找到了正確的答案,就像Dijkstra演算法所做的那樣,但仍然比Dijkstra演算法所做的要少。

A演算法只要啟發式距離不高於實際距離,就會找到一條最優路徑,就像Dijkstra演算法所做的那樣。A使用啟發式方法對節點重新排序,以便更有可能更快地遇到目標節點。

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] + graph.cost(current, next)
      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

區別:

1.如果您想要找到所有位置的路徑,請使用廣度優先搜尋或Dijkstra演算法。如果移動成本都是一樣的,使用廣度優先搜尋;如果移動成本不同,使用Dijkstra演算法。

2.如果你想找到一個位置的路徑,使用貪婪最好的第一次搜尋或A。在大多數情況下使用A。當你想要使用貪婪最好的第一次搜尋時,考慮使用一個“不可接受”的啟發式。

3 那麼最佳路徑呢?廣度優先搜尋和Dijkstra演算法保證在輸入圖中找到最短路徑。貪婪最好的第一次搜尋不是。如果啟發式永遠不會大於實際距離,則保證找到最短路徑。當啟發式變得更小時,就變成了Dijkstra演算法。當啟發式變得更大時,就變成了貪婪的第一次搜尋。

3D-A*演算法的改進:

1.更改輸入為3維的輸入,以及包含權重和障礙點。

2.更改節點的鄰居包含時間維度,即(-1,0,1)(1,0,1)(0,-1,1)(0,1,1),(0,0,1)

計算量大的改進:

3.因為時間的特殊性就是,過去了,不能回來了,根據這個特性,當沒有可走的路徑時,普通的A*是需要訪問到所有節點的,將一些不可能到達終點的一些點設為障礙點。節省了大量時間1/3的時間。