談談A*

最近忽然想到A*這個啓發式搜索,通常是用於求最短路徑的,可是感受對其估價函數還不是很清楚,其實問題也就落在了A*的有效性上面了。html

參考:算法

http://liyanblog.cn/articles/2012/09/19/1348045903617.html編程

https://en.wikipedia.org/wiki/A*_search_algorithm函數

http://baike.baidu.com/link?url=UCU0dU7DIkhKx111EQcB2DZf28Z3do3JbEQfM-l-N8hfVaApT7RUGgVo93tIN-lQtovCst0TysYGG0rd-P2KhKurl

回到A*上面,其實看A*第一眼,就會感受就是一個BFS,就是在BFS的基礎上加了一個估價函數了,而這個估價函數就是A*的關鍵所在,由於A*並不像BFS一頓狂搜,它經過這個估價函數來指導下一次搜索應該走哪一個節點,哪條路徑。這樣的好處就是在大規模的搜索中,BFS的時間複雜度確定是讓人受不了的,而這時A*就可以派上用場了。spa

 

因此對A*就出現了兩個問題了:3d

1. 究竟什麼是估價函數htm

2. 估價函數怎麼求blog

 

1. 估價函數圖片

其實估價函數仍是比較直觀,也沒怎麼繞。
定義估價函數f(x) = g(x) + h(x)


假設如今是要求A到B的路徑:
g(x): 表示從A到x的消耗,實際消耗。
h(x): 表示x到B的消耗,估計消耗。當選取的是實際的最小消耗的時效率最高了,而在如今通常K短路中就是先用SPFA等最短路算法求一下逆向最短路,而後把這個做爲h(x)進行下一步的K短路的求解了。

須要注意的是:其實這裏的消耗並不就是最短消耗或者實際消耗之類的,而是編程者給定的一個估計消耗。這裏選取的計算方式將會影響最終搜索的效率和正確與否,所以通常來講這裏消耗的選取與實際的消耗若是是正相關的話,應該就可以保證正確了。(我的見解,後面會有嚴格證實)

對於估價函數這裏,又會有兩個問題:時耗 和 正確性。

具體的時耗計算確定是與估價函數有關了,因此也會有一些狀況考慮,這裏就很少扯了,直接考慮下最差的時耗,那就是至關於估價函數沒有做用了,就是普通的BFS的消耗了。

正確性:究竟怎麼選取估價函數就是正確的,或者說是隨意選取呢?

首先能夠考慮一種極限狀況,假設咱們選取的h(x)就是實際的最短路的話,咱們能夠發現,估價函數 f(x) = g(x) + h(x)其實就是A經過x到達B的實際最短消耗,那麼咱們選取一個最小的估價值,就走那一個就可以保證是正確的了。

由於g(x)實際上是實際計算得出的消耗,所以這個咱們並非人爲隨意定的,能夠先不考慮,這時候咱們就須要關注下h(x)的選取了。

百度百科上面有一個說法:

估價值h(x)<= x到目標節點的實際消耗,這種狀況下,搜索的點數多,搜索範圍大,效率低。但能獲得最優解。
而且若是h(x)=d(x),即距離估計h(x)等於最短距離,那麼搜索將嚴格沿着最短路徑進行, 此時的搜索效率是最高的。

若是 估價值>實際值,搜索的點數少,搜索範圍小,效率高,但不能保證獲得最優解。

首先不考慮這種說法究竟是正確與否,單純從這些條件去證實就比較困難了,由於實際消耗究竟是什麼咱們是不知道的,這就比較難說明這個是正確的了。

而Wiki上面有一個證實(圖片來在Wiki):

 

這就很嚴謹了,這裏是 求 f到g的最短路。

假設條件知足: h( x ) <= d( x, y ) + h( y ),其中d(x, y)表示的是從任意x到其相鄰節點(就是有鏈接的節點)y的距離,而h(x)的含義仍是前面的從x到終點g的估計路徑了。

 

而上圖的推導就比較明顯了,能夠當作是從f出發了,而後就按照一條一條路徑走到最後的節點g了,也就是搜索的過程,這裏是假設L(P)是通過中途若干個點的最短路徑,那麼可以保證使用A*所求出來的路徑是應該都是小於等於實際的最短路徑的,那麼這時候A*是必定可以找到最短路的。

這時候咱們再回到百度百科上的說法,h(x)<= x到目標節點的實際消耗是可以找到最短路的,其實也是差很少一個意思。

其實咱們編程的時候關心的仍是究竟應該怎麼樣選取這個函數,由上面其實已經很明顯了,那就是足夠小就行,可以保證比實際對應的全部可能距離都小就Ok了,這仍是比較容易知足的,但這只是保證正確性,效率這方面仍是得仔細選取下。

 

2. 估價函數更新

直接用當前結點,對其周圍可能下一步走到的節點進行更新,主要就是更新f(x) = g(x) + h(x), g(x)是針對於上一結點的g(x)進行更新了,其他的就與上一個結點沒啥關係了。

相關文章
相關標籤/搜索