A 演算法詳解

2021-07-16 08:56:05 字數 3682 閱讀 5264

第一部分:a*演算法簡介

寫這篇文章的初衷是應乙個網友的要求,當然我也發現現在有關人工智慧的中文站點實在太少,我在這裡 

拋磚引玉,希望大家都來熱心的參與。 

還是說正題,我先拿a*演算法開刀,是因為a*在遊戲中有它很典型的用法,是人工智慧在遊戲中的代表。 

a*演算法在人工智慧中是一種典型的啟發式搜尋演算法,為了說清楚a*演算法,我看還是先說說何謂啟發式演算法。 

一、何謂啟發式搜尋演算法: 

在說它之前先提提狀態空間搜尋。狀態空間搜尋,如果按專業點的說法就是將問題求解過程表現為從 

初始狀態到目標狀態尋找這個路徑的過程。通俗點說,就是在解乙個問題時,找到一條解題的過程可以從 

求解的開始到問題的結果(好象並不通俗哦)。由於求解問題的過程中分枝有很多,主要是求解過程中求 

解條件的不確定性,不完備性造成的,使得求解的路徑很多這就構成了乙個圖,我們說這個圖就是狀態空 

間。問題的求解實際上就是在這個圖中找到一條路徑可以從開始到結果。這個尋找的過程就是狀態空間搜 

索。 常用的狀態空間搜尋有深度優先和廣度優先。廣度優先是從初始狀態一層一層向下找,直到找到目標 

為止。深度優先是按照一定的順序前查詢完乙個分支,再查詢另乙個分支,以至找到目標為止。這兩種算 

法在資料結構書中都有描述,可以參看這些書得到更詳細的解釋。 

前面說的廣度和深度優先搜尋有乙個很大的缺陷就是他們都是在乙個給定的狀態空間中窮舉。這在狀 

態空間不大的情況下是很合適的演算法,可是當狀態空間十分大,且不**的情況下就不可取了。他的效率 

實在太低,甚至不可完成。在這裡就要用到啟發式搜尋了。 

啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置 

進行搜尋直到目標。這樣可以省略大量無畏的搜尋路徑,提到了效率。在啟發式搜尋中,對位置的估價是 

十分重要的。採用了不同的估價可以有不同的效果。我們先看看估價是如何表示的。 

啟發中的估價是用估價函式表示的,如: 

f(n) 

= g(n) 

+ h(n) 

其中f(n) 

是節點n的估價函式,g(n)實在狀態空間中從初始節點到n節點的實際代價,h(n)是從n到目 

標節點最佳路徑的估計代價。在這裡主要是h(n)體現了搜尋的啟發資訊,因為g(n)是已知的。如果說詳細 

點,g(n)代表了搜尋的廣度的優先趨勢。但是當h(n) 

>> 

g(n)時,可以省略g(n),而提高效率。這些就深了, 

不懂也不影響啦!我們繼續看看何謂a*演算法。 

二、初識a*演算法: 

啟發式搜尋其實有很多的演算法,比如:區域性擇優搜尋法、最好優先搜尋法等等。當然a*也是。這些演算法 

都使用了啟發函式,但在具體的選取最佳搜尋節點時的策略不同。象區域性擇優搜尋法,就是在搜尋的過程中 

選取「最佳節點」後捨棄其他的兄弟節點,父親節點,而一直得搜尋下去。這種搜尋的結果很明顯,由於舍 

棄了其他的節點,可能也把最好的節點都捨棄了,因為求解的最佳節點只是在該階段的最佳並不一定是全域性 

的最佳。最好優先就聰明多了,他在搜尋時,便沒有捨棄節點(除非該節點是死節點),在每一步的估價中 

都把當前的節點和以前的節點的估價值比較得到乙個「最佳的節點」。這樣可以有效的防止「最佳節點」的 

丟失。那麼a*演算法又是一種什麼樣的演算法呢?其實a*演算法也是一種最好優先的演算法。只不過要加上一些約束 

條件罷了。由於在一些問題求解時,我們希望能夠求解出狀態空間搜尋的最短路徑,也就是用最快的方法求 

解問題,a*就是幹這種事情的!我們先下個定義,如果乙個估價函式可以找出最短的路徑,我們稱之為可採 

納性。a*演算法是乙個可採納的最好優先演算法。a*演算法的估價函式克表示為: 

f』(n) 

= g』(n) 

+ h』(n) 

這裡,f』(n)是估價函式,g』(n)是起點到終點的最短路徑值,h』(n)是n到目標的最斷路經的啟發值。由 

於這個f』(n)其實是無法預先知道的,所以我們用前面的估價函式f(n)做近似。g(n)代替g』(n),但 

g(n)>=g』(n) 

才可(大多數情況下都是滿足的,可以不用考慮),h(n)代替h』(n),但h(n)<=h』(n)才可(這一點特別的重 

要)。可以證明應用這樣的估價函式是可以找到最短路徑的,也就是可採納的。我們說應用這種估價函式的 

最好優先演算法就是a*演算法。哈!你懂了嗎?肯定沒懂!接著看! 

舉乙個例子,其實廣度優先演算法就是a*演算法的特例。其中g(n)是節點所在的層數,h(n)=0,這種h(n)肯 

定小於h』(n),所以由前述可知廣度優先演算法是一種可採納的。實際也是。當然它是一種最臭的a*演算法。 

再說乙個問題,就是有關h(n)啟發函式的資訊性。h(n)的資訊性通俗點說其實就是在估計乙個節點的值 

時的約束條件,如果資訊越多或約束條件越多則排除的節點就越多,估價函式越好或說這個演算法越好。這就 

是為什麼廣度優先演算法的那麼臭的原因了,誰叫它的h(n)=0,一點啟發資訊都沒有。但在遊戲開發中由於實 

時性的問題,h(n)的資訊越多,它的計算量就越大,耗費的時間就越多。就應該適當的減小h(n)的資訊,即 

減小約束條件。但演算法的準確性就差了,這裡就有乙個平衡的問題。可難了,這就看你的了! 

好了我的話也說得差不多了,我想你肯定是一頭的霧水了,其實這是寫給懂a*演算法的同志看的。哈哈! 

你還是找一本人工智慧的書仔細看看吧!我這幾百字是不足以將a*演算法講清楚的。只是起到拋磚引玉的作用 

希望大家熱情參與嗎! 

預知a*演算法的應用,請看《深入a*演算法》。

第二部分:深入a*演算法———**a*演算法在搜尋最短路徑中的應用

一、前言 

在這裡我將對a*演算法的實際應用進行一定的**,並且舉乙個有關a*演算法在最短路徑搜尋 

的例子。值得注意的是這裡並不對a*的基本的概念作介紹,如果你還對a*演算法不清楚的話, 

請看姊妹篇《初識a*演算法》。 

二、a*演算法的程式編寫原理 

我在《初識a*演算法》中說過,a*演算法是最好優先演算法的一種。只是有一些約束條件而已。 

我們先來看看最好優先演算法是如何編寫的吧。 

如圖有如下的狀態空間:(起始位置是a,目標位置是p,字母後的數字表示節點的估價值) 

搜尋過程中設定兩個表:open和closed。open表儲存了所有已生成而未考察的節點,closed 

表中記錄已訪問過的節點。演算法中有一步是根據估價函式重排open表。這樣迴圈中的每一 

步只考慮open表中狀態最好的節點。具體搜尋過程如下: 

1)初始狀態: 

open=[a5];closed=; 

2)估算a5,取得搜有子節點,並放入open表中; 

open=[b4,c4,d6];closed=[a5] 

3)估算b4,取得搜有子節點,並放入open表中; 

open=[c4,e5,f5,d6];closed=[b4,a5] 

4)估算c4;取得搜有子節點,並放入open表中; 

open=[h3,g4,e5,f5,d6];closed=[c4,b4,a5] 

5)估算h3,取得搜有子節點,並放入open表中; 

open=[o2,p3,g4,e5,f5,d6];closed=h3c4,b4,a5] 

6)估算o2,取得搜有子節點,並放入open表中; 

open=[p3,g4,e5,f5,d6];closed=[o2,h3,c4,b4,a5] 

7)估算p3,已得到解; 

A 演算法詳解

a 演算法的基本原理 a star演算法是一種靜態路網中求解最短路徑最有效的直接搜尋方法,也是解決許多搜尋問題的有效演算法。演算法中的距離估算值與實際值越接近,最終搜尋速度越快。f i g i h i 以上式子中 g i 表示從起點到當前節點已經付出的代價,這個是準確的 a 演算法最重要的是估價函式...

KMP演算法詳解

模式匹配的kmp演算法詳解 這種由d.e.knuth,j.h.morris和v.r.pratt同時發現的改進的模式匹配演算法簡稱為kmp演算法。大概學過資訊學的都知道,是個比較難理解的演算法,今天特把它搞個徹徹底底明明白白。注意到這是乙個改進的演算法,所以有必要把原來的模式匹配演算法拿出來,其實理解...

KMP演算法詳解

kmp演算法即knuth morris pratt演算法,是模式匹配的一種改進演算法,因為是名字中三人同時發現的,所以稱為kmp演算法。因為偶然接觸到有關kmp的問題,所以上網查了一下next陣列和 nextval陣列的求法,卻沒有找到,只有在csdn的資料檔案裡找到了next陣列的簡單求法 根據書...