1. 程式人生 > >A*搜索算法

A*搜索算法

return lose 所有 brush img ati tween 做了 search

2018-03-17 18:15:47

A*搜索算法是最短路徑問題中另一個非常經典的算法。A*算法常用於遊戲中的NPC的移動計算,或網絡遊戲的BOT的移動計算上。

該算法綜合了Best-First Search和Dijkstra算法的優點:在進行啟發式搜索提高算法效率的同時,可以保證找到一條最優路徑(基於評估函數)。

技術分享圖片

下面舉例說明這個算法的過程,舉例用的網絡如下,從S - > G:

技術分享圖片

方法一、僅采用積累距離

算法流程:

Get the end,break

          |

Initial Queue --> Test First Path --> Extend First Path , sorted by ACC

          |——————————|

技術分享圖片

由於我每次都擴展的最小的積累距離值,所以第取出G的時候,就是G為最短路確定的時候,因為任何其他的路都比S - ?G長,而且日後也不可能更短。

其實這就是Dijkstra算法。當然在這裏,我做了很多無效的extend,如果維護一個extend表,那麽效率將會有很大的提升。

方法二、啟發式距離 + 擴展列表

上面的Dijkstra方法不好的地方是很明顯的,這種方法沒有方向性,是一種發散式的搜索,事實上,運行一遍Dijkstra可以將源點到其他所有點的最短路徑求出來。

然而,在很多問題中,我們並不需要源點到其他結點的距離信息,我們只關系源點到目的地的最短路徑,這時候就可以使用啟發式的距離,來讓路徑的生成變得有方向性。

具體做法就是將上面的選擇過程中積累長度變成積累長度 + 啟發式距離。

在找到一條路徑後還需向下探查,直到其他路都絕無可能為止。

技術分享圖片

另外,這裏加上了擴展列表,也就是已經擴展過的不會再繼續擴展,這就是A*算法的思路。

A* = 分支限界 + 擴展列表 + 可容許啟發式路徑。

 function A*(start,goal)
     closedset := the empty set                 //已經被估算的節點集合
     openset := set containing the initial node //將要被估算的節點集合,初始只包含start
     came_from := empty map
     g_score[start] := 0                        //g(n)
     h_score[start] := heuristic_estimate_of_distance(start, goal)    //通過估計函數 估計h(start)
     f_score[start] := h_score[start]            //f(n)=h(n)+g(n),由於g(n)=0,所以省略
     while openset is not empty                 //當將被估算的節點存在時,執行循環
         x := the node in openset having the lowest f_score[] value   //在將被估計的集合中找到f(x)最小的節點
         if x = goal            //若x為終點,執行
             return reconstruct_path(came_from,goal)   //返回到x的最佳路徑
         remove x from openset      //將x節點從將被估算的節點中刪除
         add x to closedset      //將x節點插入已經被估算的節點
         for each y in neighbor_nodes(x)  //循環遍歷與x相鄰節點
             if y in closedset           //若y已被估值,跳過
                 continue
             tentative_g_score := g_score[x] + dist_between(x,y)    //從起點到節點y的距離
 
             if y not in openset          //若y不是將被估算的節點
                 add y to openset         //將y插入將被估算的節點中
                 tentative_is_better := true     //暫時判斷為更好
             elseif tentative_g_score < g_score[y]         //如果起點到y的距離小於y的實際距離
                 tentative_is_better := true         //暫時判斷為更好
             else
                 tentative_is_better := false           //否則判斷為更差
             if tentative_is_better = true            //如果判斷為更好
                 came_from[y] := x                  //將y設為x的子節點
                 g_score[y] := tentative_g_score    //更新y到原點的距離
                 h_score[y] := heuristic_estimate_of_distance(y, goal) //估計y到終點的距離
                 f_score[y] := g_score[y] + h_score[y]
     return failure
 
 function reconstruct_path(came_from,current_node)
     if came_from[current_node] is set
         p = reconstruct_path(came_from,came_from[current_node])
         return (p + current_node)
     else
         return current_node

A*搜索算法