深入了解A

2022-03-16 03:31:20 字數 2900 閱讀 8749

一、前言

在這裡我將對a*演算法的實際應用進行一定的**,並且舉乙個有關a*演算法在最短路徑搜尋的例子。值得注意的是這裡並不對a*的基本的概念作介紹,如果你還對a*演算法不清楚的話,請看姊妹篇《初識a*演算法》。

這裡所舉的例子是參考amit主頁中的乙個源程式,使用這個源程式時,應該遵守一定的公約。

二、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=[h3,c4,b4,a5]

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

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

7)估算p3,已得到解;

看了具體的過程,再看看偽程式吧。演算法的偽程式如下:

best_first_search()

for(每乙個x的子節點y)

//還沒有排序

else

if(y在open表中)

else

//y在close表中

}將x節點插入close表中;

按照估價值將open表中的節點排序;

}//end for

}//end while

}//end func

啊!偽程式出來了,寫乙個源程式應該不是問題了,依葫蘆畫瓢就可以。a*演算法的程式與此是一樣的,只要注意估價函式中的g(n)的h(n)約束條件就可以了。不清楚的可以看看《初識a*演算法》。好了,我們可以進入另乙個重要的話題,用a*演算法實現最短路徑的搜尋。在此之前你最好認真的理解前面的演算法。不清楚可以找我。我的email在文章尾。

三、用a*演算法實現最短路徑的搜尋

先複習一下,a*演算法的核心是估價函式f(n),它包括g(n)和h(n)兩部分。g(n)是已經走過的代價,h(n)是n到目標的估計代價。在這個例子中g(n)表示在狀態空間從起始節點到n節點的深度,h(n)表示n節點所在地圖的位置到目標位置的直線距離。啊!乙個是狀態空間,乙個是實際的地圖,不要搞錯了。再詳細點說,有乙個物體a,在地圖上的座標是(xa,ya),a所要到達的目標b的座標是(xb,yb)。則開始搜尋時,設定乙個起始節點1,生成八個子節點2- 9

因為有八個方向。如圖:

仔細看看節點1、

9、17的g(n)和h(n)是怎麼計算的。現在應該知道了下面程式中的f(n)是如何計算的吧。開始講解源程式了。其實這個程式是乙個很典型的教科書似的程式,也就是說只要你看懂了上面的偽程式,這個程式是十分容易理解的。不過他和上面的偽程式有一些的不同,我在後面會提出來。

先看搜尋主函式:

void astarpathfinder::findpath(int sx, int sy, int dx, int

dy) path =bestnode;

}  再看看生成子節點函式:

void astarpathfinder::generatesuccessors(node *bestnode, int dx, int

dy)

看看最重要的函式:

void astarpathfinder::generatesucc(node *bestnode,int x, int y, int dx, int

dy) }

else

//在closed表中嗎?

//if equal to null then not in open list, else it returns the node in old

if ( (old=checkclosed(tilenums)) !=null )

}//不在open表中也不在close表中

else

}  哈哈!a*演算法我懂了!當然,我希望你有這樣的感覺!不過我還要再說幾句。仔細看看這個程式,你會發現,這個程式和我前面說的偽程式有一些不同,在generatesucc函式中,當子節點在closed表中時,沒有將子節點從closed表中刪除並放入open表中。而是直接的重新的計算該節點的所有子節點的估價值(用propagatedown函式)。這樣可以快一些!另當子節點在open表和closed表中時,重新的計算估價值後,沒有重新的對open表中的節點排序,我有些想不通,為什麼不排呢?:-(,會不會是乙個小小的bug。你知道告訴我好嗎?

好了!主要的內容都講完了,還是完整仔細的看看源程式吧!希望我所的對你有一點幫助,一點點也可以。如果你對文章中的觀點有異議或有更好的解釋都告訴我。我的email在文章最後!

公司的程式用的就是這個a*,剛開始將的明白,後面說的不咋明白啊,叫我控制步驟多少,我感覺這個是動態的怎麼控制步數多少呢?

深入了解A

一 前言 在這裡我將對a 演算法的實際應用進行一定的 並且舉乙個有關a 演算法在最短路徑搜尋的例子。值得注意的是這裡並不對a 的基本的概念作介紹,如果你還對a 演算法不清楚的話,請看姊妹篇 初識a 演算法 這裡所舉的例子是參考amit主頁中的乙個源程式,使用這個源程式時,應該遵守一定的公約。二 a ...

深入了解Dojo Data

譯自http www.sitepen.com blog 2010 10 13 dive into dojo data 使用dojo data有助於快速建立web應用的介面,且易於嵌入各種資料來源。它在使用者介面與底層資料之間提供了一層抽象層,使得使用者介面開發人員能夠專注於ui的開發,而無需擔心資料...

深入了解CCtrlView

如果我們要將乙個控制項轉換成檢視類,我們一般會想到cctrlview,用它實現的控制項檢視一般新增乙個get ctrl函式,函式的作用是返回檢視中控制項的引用,如果在mfc程式中跟蹤它的呼叫我們會發現它的實現是這樣的 以cedit控制項為例 afxext inline cedit ceditview...