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的格仔 移動到空位上。給定乙個初始的棋盤,怎樣才能經過移動變成如下目標棋盤 為...