八數碼問題的啟發式搜尋方法 A 搜尋

2021-09-28 16:20:00 字數 4414 閱讀 1917

在3×3棋盤上,放有1到8八個數碼,有1個方格是空的,空位置用0表示,對空格依次執行左移、右移、上移和下移這四個操作,使得棋盤從初始狀態到目標狀態。本次實驗中以如下初始狀態和目標狀態為例:

本次啟發式搜尋是在廣度優先遍歷的基礎上給出啟發資訊的搜尋,然後在每一層結點中利用啟發資訊找乙個最優結點,然後在這個最優結點的基礎上再擴充套件下一層,重複上述操作,直到找到目標結點。

啟發資訊:找結點的距離dist與結點的深度dep之和最小的結點,即為當前層最優結點。

其中dist是由曼哈頓距離給出,曼哈頓距離——兩點在南北方向上的距離加上在東西方向上的距離,即d(i,j)=|xi-xj|+|yi-yj|。

例如:求左邊結點node_up到右邊目標結點的dist

初設distance=0

node_up.digit[0][0]=dest.digit[0][1] distance+=|0-0|+|0-1|=1

node_up.digit[0][1]=dest.digit[1][1] distance+=|0-1|+|1-1|=1+1=2

node_up.digit[0][2]=dest.digit[0][2] distance+=|0-0|+|2-2|=2+0=2

node_up.digit[1][0]=dest.digit[0][0] distance+=|1-0|+|0-0|=2+1=3

node_up.digit[1][1]=dest.digit[1][0] distance+=|1-1|+|1-0|=3+1=4

node_up.digit[1][2]=dest.digit[1][2] distance+=|1-1|+|2-2|=4+0=4

node_up.digit[2][0]=dest.digit[2][0] distance+=|2-0|+|0-0|=4+0=4

node_up.digit[2][1]=dest.digit[2][1] distance+=|2-2|+|1-1|=4+0=4

node_up.digit[2][2]=dest.digit[2][2] distance+=|2-2|+|2-2|=4+0=4

dist_up=distance=4;

即該結點的dist=4

在這個搜素樹中,可以清晰的看到整個搜尋過程:

注意:

移動結點中0數碼時,要先定位到結點中的0數碼的座標位置(x,y),例如初始結點的0數碼座標位置(x,y)是(1,1),當然我們可以看到x>0時才能進行上移,x<2才能進行下移,y>0才能進行左移,y<2才能進行右移。

index 索引值是為了輸出由初始結點到目標結點的路徑而設定的

初始結點0先與目標結點對比,如果不一致則繼續下列步驟,一致則開始輸出。

初始結點0經過上、下、左、右移動可以擴充套件為結點1、2、3、4,然後再更新結點1、2、3、 4的索引 index 為上層初始結點0的下標0。即由初始第一層到第二層的擴充套件完成,再分別計算第二層結點的dist,再在這一層中找到 min(dist+dep) 的結點,即就是結點1為最小啟發資訊的結點,也就是這層的最優點。與目標結點對比,不一致則繼續下列步驟。

再以結點1經過移動擴充套件結點:但是發現不能上移,下移之後的結點與之前的結點0有相同,左移得到結點5,右移得到結點6,所以不能歸為這一層。然後再更新結點5、 6的索引 index 為上層初始結點1的下標1。再分別計算第三層結點的dist,再在這一層中找到 min(dist+dep) 的結點,即就是結點5為最小啟發資訊的結點,也就是這層的最優點。與目標結點對比,如果不一致則繼續下列步驟。

再以結點5經過移動擴充套件結點:但是發現不能上移,下移之後得到結點7,不能左移,右移之後的結點與之前的結點1有相同,所以不能歸為這一層。然後再更新結點7 的索引 index 為上層初始結點5的下標5。再分別計算第四層結點的dist,再在這一層中找到 min(dist+dep) 的結點,即就是結點7為最小啟發資訊的結點,也就是這層的最優點。與目標結點對比,不一致則繼續下列步驟。

再以結點7經過移動擴充套件結點:但是發現上移之後的結點與結點5相同,下移之後得到結點8,不能左移,右移之後得到結點9。然後再更新結點9 的索引 index 為上層初始結點7的下標7。再分別計算第四層結點的dist,再在這一層中找到 min(dist+dep) 的結點,即就是結點7為最小啟發資訊的結點,也就是這層的最優點。與目標結點對比,發現一致,則開始輸出。

(這個**是參考別人的,本人僅僅對其進行分析)

```cpp

#include #include #include #includeusing namespace std;

const int row = 3;

const int col = 3;

const int maxdistance = 10000;

const int maxnum = 10000;

int abs(int a)

typedef struct _node node;

node src, dest;

vectornode_v; // 儲存節點

bool isemptyofopen()

return true;

}bool isequal(int index, int digit[col])

return true;

}ostream& operator<

return os;

}void printsteps(int index, vector& rstep_v)

for (int i = rstep_v.size() - 1; i >= 0; i--)

cout << "step " << rstep_v.size() - i

<< endl << rstep_v[i] << endl;

}void swap(int& a, int& b)

void assign(node& node, int index)

int getminnode()

} return loc;

}bool i***pandable(node& node)

return true;

}int distance(node& node, int digit[col])

else

flag = false;

}if (flag)

break;

}return distance;

}int mindistance(int a, int b)

void processnode(int index)

else flag = false;

} if (flag)

break;

} node node_up; //上移操作

assign(node_up, index);

int dist_up = maxdistance;

if (x > 0) //上移x=0位於第一行,不能上移 }

node node_down; //下移操作

assign(node_down, index);

int dist_down = maxdistance;

if (x < 2)

} node node_left;//左移操作

assign(node_left, index);

int dist_left = maxdistance;

if (y > 0)

} node node_right; //右移操作

assign(node_right, index);

int dist_right = maxdistance;

if (y < 2)

} node_v[index].dist = maxnum;

}int main()

src.index = 0;

src.dep = 1;

cout << "輸入目標狀態" << endl;

for (int m = 0; m < row; m++)

for (int n = 0; n < col; n++)

node_v.push_back(src);

while (1)

else

else

processnode(loc);

} }system("pause");

return 0;

}

八數碼問題 啟發式搜尋

一 問題描述 在乙個3 3 的方棋盤上放置著 1,2,3,4,5,6,7,8 八個數碼 每個數碼佔一格 且有乙個空格。這些數碼可以在棋盤上移動,其移動規則是 與空格相鄰的數碼方格可以移入空格。現在的問題是 對於指定的初始棋局和目標棋局,給出數碼的移動序列。該問題稱八數碼難題或者重排九宮問題。原始碼 ...

八數碼問題 啟發式搜尋

我們在搜尋的時候往往會發現一些資料會導致我們的普通的深搜與廣搜都無法通過,那這個時候我們就需要讓起點與終點建立一些聯絡,今天我們講述的啟發式搜尋就是在廣度優先搜尋的基礎上加了這樣乙個優化,叫做估價函式。對於乙個狀態,在我們知道終點狀態的時候,我們可以設計乙個估價函式使我們對這個狀態距離終點的距離有個...

A 啟發式搜尋 八數碼問題

a 啟發式搜尋 include iostream include stdlib.h include conio.h include include define size 3 using namespace std 定義二維陣列來儲存資料表示某乙個特定狀態 typedef int status si...