搜尋 A 演算法和IDA 演算法

2021-10-08 07:06:12 字數 3810 閱讀 6850

a*演算法概述:

採用廣度優先搜尋策略,在搜尋過程中使用啟發函式,即有大致方向的向前進雖然目標有時候不是很明確。

a*演算法核心:

a演算法的關鍵在於啟發函式,啟發函式的優劣直接影響a演算法的效率。

f(n)=g(n)+h(n);

這個式子中:f(n)表示從初始狀態到目標狀態的估測代價。

g(n)表示從初始狀態到當前狀態的代價(已經確定)。

h(n)表示從當前狀態到目標狀態的估測代價(**)。

其中:h(n)的好壞直接影響評估函式的好壞。

乙個好的f(n)總能明確指引演算法前進的方向,可以迅速的到達目標狀態。

f*(n)=g*(n)+h*(n); 我們假設的從初始狀態到目標狀態的實際最小代價。

這個式子中:f(n)表示從初始狀態到目標狀態的實際代價。

g*(n)表示從初始狀態到當前狀態的代價(已經確定)g*(n)和g(n)是相等的。

h*(n)表示從當前狀態到目標狀態的實際代價。

若h(n)<=h*(n),則總能找到最優解。(當h(n)優點:

與廣度優先搜尋策略和深度優先搜尋策略相比,a*演算法不是盲目搜尋,而是有提示的搜尋。

缺點:

該演算法一般要使用大量的空間用於儲存已搜尋過的中間狀態,防止重複搜尋。

用途:

從初始狀態出發 =>經過一系列中間狀態 =>最終到達目標狀態(或者無法到達)。

該演算法用於經過中間狀態時候的行進策略(其中的中間狀態或者由題目給出,或者在前邊已經推導得出)。

ida*演算法:

迭代加深搜尋演算法,在搜尋過程中採用估值函式,以減少不必要的搜尋。

ida*演算法核心:

設定每次可達的最大深度depth,若沒有到達目標狀態則加深最大深度。

採用估值函式,剪掉f(n)大於depth的路徑。

優點:

使用回溯方法,不用儲存中間狀態,大大節省了空間。

缺點:

重複搜尋:回溯過程中每次depth變大都要再次從頭搜尋。

用途:和a*演算法大致相同。

a*演算法(a-star)

為了賦予計算機「智慧型」,我們必須更有智慧型(?),計算機可以通過乙個「估價函式」確定乙個狀態的「前途」的量,人呢……必須找到這個估價函式。

通常,估價函式計為f(n),f中,^在f上方,讀作f-hat(帽子)。估價函式的定義如下:

f(n)=g(n)+h^(n)

n是狀態的表示,通常是狀態的編號之類的。在程式設計中,可以寫作f_hat()或者直接寫成f()即可。

g^(n)表示從初始狀態到n 總共花費的代價。

h(n)表示從n到目標狀態估計需要花費的代價,對於乙個正確的搜尋,h(n)<=h(n),h(n)表示從n到目標狀態的實際代價(沒有算出來的時候,當然是求不出來h(n)的,但是可以找到乙個h(n)<=h(n)哦),在這個範圍內,h(n)越接近h(n),搜尋的啟發效果越好。

對於h1(n)和h2(n),如果存在h1(n)2(n)<=h(n),且h1(n)<=h2(n),我們說h2(n)比h1(n)更靈通(more informed)。

f(n)的值就是對n這個狀態的估價。這個估價主要體現在h(),因為g()是已知的;g()體現了廣度優先,當h()>g()時,可以省略g^()從而提高效率。

搜尋中,每到新的狀態,計算它的f()值,在目前所有的狀態中,優先擴充套件f()最小的,如果f()最小的中有很多,則優先擴充套件其中g()最大的。

這麼說好像十分抽象,我們用乙個例子理解它:

對於迷宮

#############

#a##

#########

######_###

#__________b#

#############

a表示起點,b表示終點,#表示牆,_表示路。

求最短路時,若用廣度優先搜尋,則會同時搜尋(即互不干擾)各條路徑,如果是人,一定不會這樣做,因為用「瞪眼法」可以看出下、右使最好的方法,但是計算機不能,所以我們要寫乙個函式來啟發它。

本例中g就是到當前狀態走了多少步,那麼,估計值h怎麼辦呢?我們知道,在迷宮上不能走斜路,所以說,從某個個點到終點,假設到終點都是路,那麼最少的步數就是從該點到終點的歐幾里得距離(橫座標差的絕對值+縱座標差的絕對值),如果有牆,最少的步數有可能比歐幾里得距離要大,所以說,用歐幾里得距離作為估價函式是可以的。

h^(n)=point[n].euclid(target)

那麼,在搜尋時,到達了(4,3)的時候,會擴充套件向上的和向右的,

向上的:

f^() = g^() + h^() = 6 + 8 = 14

向右的:

f^() = g^() + h^() = 6 + 7 = 13

所以向右的狀態先被搜尋(和擴充套件的順序無關)。

為了實現每次獲取當前狀態中最有前途的狀態,我們需要乙個「優先佇列」,每次取出最有前途的,這用堆實現。

顯然,當此h^()=0時,已經找到答案。

偽**:

class status

status *goup();status *godown();status *goleft();status *goright();

int g_hat()

int h_hat()

int f_hat()

};//heap用f_hat()(小在前),相同的,用g_hat()(大在前)。

while (!heap.isnull())

另外,八數碼問題可以用a*演算法實現,一種估價函式是「不在正確位置上的數字的個數」,另乙個更靈通的估價函式是所有數字(包括空格)到正確位置的歐幾里得距離的一半。(思考:為什麼是一半?答案:因為一次相當於交換了兩個數字,如果把空格看作數字0,所以說應該是一半,如果不一半,則搜尋可能不是最短路)

廣度優先搜尋是a*演算法的乙個特例,它的g^(n)=0,沒有任何啟發資訊。

ida演算法(迭代加深的a演算法)

引例:the rotation game(poj 2286)

->原題鏈結

這個遊戲中,你有乙個這樣的東西:

a~h表示所在的行或者列向其方向迴圈移動一格。

目標是使得**的八個格仔的數相同。

輸入保證數字只有1、2、3,且分別8個。求最少步驟的方式(a~h表示),並求出此時**的數字。

這個問題用a不是好的選擇,因為狀態擴充套件太多,判重不易,所以我們用迭代加深的a演算法。

ida*的基本步驟:

1、設定最大的深度maxf = f^(初始狀態)

2、ids搜尋,棄去f^()>maxf的情況,如果找到答案,則結束

3、如果沒有答案:若搜尋**現了比maxf更大的f^(),則令maxf = 其中最小的值,重複2;如果沒有,則說明沒有答案

那麼,剛才的問題可以表示為:(h^() = 8 - 中間的八個方格**現次數最多的數出現的次數)

int f_hat() 

bool idastar()

//返回:是否找到答案

if (h_hat() == 0) return true;

++steps;

foreach(變換)

--steps;

return false;

}int main()

同樣,ids是乙個特殊的ida*演算法,它的h^()=0,也沒有啟發資訊。

ida演算法解析

int sub 401130 sub 402702 yes,you get it return 0 bool thiscall sub 401000 int this else return result 這是演算法的具體內容,這裡出現的第乙個問題就是 v4的值 char v4 48 sp 0h b...

POJ 2286 IDA 搜尋(迭代加深搜尋演算法)

ida 搜尋又成為迭代加深搜尋,感覺迭代加深這個稱謂就基本概括了這種搜尋算沒的核心。首先所以討論一下什麼迭代加深搜尋,深度優先搜尋乙個局面可以搜尋很多很多層,這種情況很可能時間啊複雜度很大 怎麼辦呢?聰明的人們想到了限制限制了搜尋深度,正是所謂的迭代加深搜尋,就是在深度無上限的情況下,先預估乙個深度...

IDA 演算法 騎士精神

騎士精神 description 在乙個5 5的棋盤上有12個白色的騎士和12個黑色的騎士,且有乙個空位。在任何時候乙個騎士都能按照騎士的走法 它可以走到和它橫座標相差為1,縱座標相差為2或者橫座標相差為2,縱座標相差為1的格仔 移動到空位上。給定乙個初始的棋盤,怎樣才能經過移動變成如下目標棋盤 為...