三種距離 A 演算法解八數碼問題

2021-08-09 23:36:15 字數 4066 閱讀 4250

曼哈頓距離

(計程車距離)走網格線的矩形路線

歐氏距離

以空間為基準的兩點之間最短距離

切比雪夫距離

維度為3及以上,例,出物理距離外,還要加上財力等權值。

明氏距離

明科夫斯基距離

維度為1時,等價與曼哈頓距離

為2時,等價與歐式距離

3及以上,等價於切比雪夫距離

漢明距離

在資訊理論中,兩個等長字串之間的漢明距離是兩個字串對應位置的不同字元的個數。換句話說,它就是將乙個字串變換成另外乙個字串所需要替換的字元個數。

八數碼問題

八數碼問題也稱為九宮問題。在3×3的棋盤,擺有八個棋子,每個棋子上標有1至8的某一數字,不同棋子上標的數字不相同。棋盤上還有乙個空格,與空格相鄰的棋子可以移到空格中。要求解決的問題是:給出乙個初始狀態和乙個目標狀態,找出一種從初始轉變成目標狀態的移動棋子步數最少的移動步驟。所謂問題的乙個狀態就是棋子在棋盤上的一種擺法。棋子移動後,狀態就會發生改變。解八數碼問題實際上就是找出從初始狀態到達目標狀態所經過的一系列中間過渡狀態。八數碼問題一般使用搜尋法來解。

判斷是否有解

每乙個狀態可認為是乙個1×9的矩陣,問題即通過矩陣的變換,是否可以變換為目標狀態對應的矩陣?由數學知識可知,可計算這兩個有序數列的逆序值,即每乙個數之前小於它的數字的個數之和(0表示空格,不包括0)。如果兩者都是偶數或奇數,則可通過變換到達,否則,這兩個狀態不可達。

搜尋方法

僅為空格制定4種走步,因為只有緊靠空格的棋牌才能移動。

空格移動的唯一約束是不能移出棋盤。 廣度

bfs將每次搜尋結果放在open表末端

深度dfs

將每次搜尋結果放在open表前端

往往給出乙個節點擴充套件的最大深度——深度界限。

啟發式搜尋

重排open表,選擇最有希望的節點加以擴充套件

啟發式搜尋就是在狀態空間中的搜尋對每乙個搜尋的位置進行評估,得到最好的位置,再從這個位置進行搜尋直到目標。對位置的估價是十分重要的,採用了不同的估價可以有不同的效果。

啟發中的估價是用估價函式表示的,如:f(n) = g(n) +h(n)其中f(n) 是節點n的估價函式,g(n)是在狀態空間中從初始節點到n節點的實際代價,h(n)是從n到目標節點最佳路徑的估計代價。在此八數碼問題中,顯然g(n)就是從初始狀態變換到當前狀態所移動的步數,h(n)為不在目標位的棋子個,即錯位數。

a*

在最短路徑搜尋效率上,一般有a*>dijkstra、雙向bfs,其中dijkstra、雙向bfs到底哪個演算法更優,還得看具體情況。

a*演算法最為核心的過程,就在每次選擇下乙個當前搜尋點時,是從所有已探知的但未搜尋過點中(可能是不同層,亦可不在同一條支路上),選取f值最小的結點進行展開。而所有「已探知的但未搜尋過點」可以通過乙個按f 值公升序的佇列(即優先佇列)進行排列。

如果重排open表是依據f(n)=g(n)+h(n)進行的,則稱該過程為a演算法。在a演算法中,如果對所有的n存在h(n)≤h*(n),則稱h(n)為h*(n)的下界,它表示某種偏於保守的估計。採用h*(n)的下界h(n)為啟發函式的a演算法,稱為a*演算法。當h=0時,a*演算法就變為有序搜尋演算法。

在a演算法中,如果滿足條件:

(1) g(n)是對g*(n)的估計,且g(n)>0;

(2) h(n)是h*(n)的下界,即對任意節點n均有0≤h(n)≤h*(n)則a演算法稱為a*

a*演算法的可納性,對任乙個圖,存在從s到目標的路徑,如果乙個搜尋演算法總是結束在一條從s到目標的最佳路徑上,則稱此演算法是可採納的。演算法a*保證只要最短路徑存在,就一定能找出這條路徑,所以演算法a*是可納的。

估價函式:

(1)f(n)=d(n)+w(n) 

其中:d(n)為n的深度w(n)為不在位的棋子數

取h(n)=w(n),則有w(n)≤h*(n),h(n)滿足a*演算法的限制條件。

(2)f(n)=d(n)+p(n)

啟發函式h(n)=p(n),p(n)為不在位的棋子與其目標位置的距離之和,則有p(n)≤h*(n),滿足a*演算法的限制條件。

w(n)——不在位的棋子數,不夠貼切,錯誤選用節點加以擴充套件。

更接近於h*(n)的h(n),其值是節點n與目標狀態節點相比較,每個錯位棋子在假設不受阻攔的情況下,移動到目標狀態相應位置所需走步的總和。p(n)比w(n)更接近於h*(n),因為p(n)不僅考慮了錯位因素,還考慮了錯位的距離(移動次數)。

說明h值越大,啟發功能越強,搜尋效率越高.特別地

(1)h(n)=h*(n)     搜尋僅沿最佳路徑進行,效率最高.

(2)h(n)=0        無啟發資訊, 盲目搜尋,效率低.

(3)h(n)>h*(n)    是一般的a演算法,效率高,但不能保證找到最佳路徑. 有時為求解難題取h(n)>h*(n), 以提高效率. 

//節點結構體

typedef struct node node,*lnode;

//open closed 表結構體

typedef struct stack stack,* lstack;

//選取 open 表上 f 值最小的節點,返回該節點位址

node * minf(lstack * open)

temp = temp->next;

}將該節點從open表上刪除

minx = min->npoint;

temp = minp->next;

minp->next = minp->next->next;

free(temp);

return minx;

}//判斷是否可解  1表示可解

某狀態和目標狀態

int canslove(node * suc, node * goal)

if(a%2 == b%2)           若同為偶數或同為奇數

return 1;

else

return 0;

}//判斷節點是否相等 ,1 相等,0 不相等

int equal(node * suc,node * goal)

//判斷節點是否屬於 open 表 或 closed 表,是則返回節點位址,否則返回空位址

node * belong(node * suc,lstack * list)

return null;

}//把節點放入 open 或 closed 表中 插入表

void putinto(node * suc,lstack * list)

///計算 f 值部分-開始//

double fvalue(node suc, node goal, float speed)

double distance(node suc, node goal, int i)

錯位行數與錯位列數和

return double(fabs(h1/3 - h2/3) + fabs(h1%3 - h2%3));

}///計算 f 值部分-結束//

///擴充套件後繼節點部分的函式-開始/

*int belongprogram(lnode * suc ,lstack * open ,lstack * closed ,node goal ,float speed)

}else

return flag;

}void spread(lnode * suc, lstack * open, lstack * closed, node goal, float speed)}}

///擴充套件後繼節點部分的函式-結束//

node * process(lnode * org, lnode * goal, lstack * open, lstack * closed, float speed)

}int shownum(node * result)

}printf("\n");

return n+1;}}

A 演算法 解經典八數碼問題

題目連線 問題引入 在進行bfs搜尋的過程中,只能說明起始狀態距離該狀態的代價最小,但是在未來的搜尋中,該狀態到目標狀態的可能會花費更高的代價,導致最優解的搜尋量增大。為了提高搜尋效率,可以讓那些代價大的方案盡可能的在後面進行搜尋,此時就需要引入a 演算法。做法 設計乙個估值函式f state 估值...

演算法 三種博弈問題

有一種很有意思的遊戲,就是有物體若干堆,可以是火柴棍或是圍棋子等等均可。兩個人輪流從堆中取物體若干,規定最後取光物體者取勝。這是我國民間很古老的乙個遊戲,別看這遊戲極其簡單,卻蘊含著深刻的數學原理。下面我們來分析一下要如何才能夠取勝。一 巴什博奕 bash game 只有一堆n個物品,兩個人輪流從這...

八皇后問題的三種解法

會下西洋棋的人都很清楚 皇后可以在橫 豎 斜線上不限步數地吃掉其他棋子。如何將8個皇后放在棋盤上 有8 8個方格 使它們誰也不能被吃掉!這就是著名的八皇后問題。對於某個滿足要求的8皇后的擺放方法,定義乙個皇后串a與之對應,即a b1b2 b8,其中bi為相應擺法中第i行皇后所處的列數。已經知道8皇后...