終於自己ac了這道八數碼難題,用的方法是最最普通的單項bfs+hash,這裡主要的難點在於如何儲存狀態,其實,在八數碼裡所有的狀態共有9!種=362880種,所以在每個轉台節點,我需要乙個char state[3][3]來記錄當前棋盤的狀態,用乙個int x,y來記錄當前x的位置,用char operation來記錄從父狀態到這個狀態需要進行的操作,當然,為了記錄路徑,我需要記錄它的父節點,然而這個父節點要怎麼去記錄呢,剛開始的時候對於這個問題糾結了很久,曾經直接把結構體存在佇列裡面,然後用指標去引用它的父節點,殊不知,當出隊操作後,宣告的節點就是去了意義,所以這種做法是錯誤的。看了別人的思路,把所有的狀態節點都存在乙個結構體陣列裡面,並且用乙個count記錄當錢陣列裡面狀態的個數,因為每出來乙個新狀態,就把它賦值給相應的陣列元素。所以,乙個狀態的父狀態就可以指向父狀態的陣列下表index,到時候可以直接讀取。還有一點需要注意的是進行hash時,不同的max取值可能會導致不同的結果,一般講max取較大的素數,事實證明,用stl 來存狀態去重效率會低很多,用hash的話效率會高一些。對於路徑的尋找,既然知道了每一狀態的操作,則可以從目標狀態開始將操作壓棧,到時候出棧即為正確的從初始態到目標態的操作。
#include#include#include#include#include#include#includeusing namespace std;
#define max 8000003
struct node
allstate[400000];
int hash[max];
//setstateset;
queuequ;
stackpath;
int dirx[4]=;
int diry[4]=;
int gethash(node n)
void getpath(node target)
}void bfs(node head)
int x=allstate[index].x;
int y=allstate[index].y;
for(i=0;i<4;i++)
if(diry[i]==0)
qu.push(statecount);
allstate[statecount++]=newnode;
} }if(!isok)
getpath(outnode);
while(!path.empty())
}} head.parent=-1;
head.operation='0';
bfs(head);
return 0;
}
POJ1077 經典的八數碼問題
很經典的八數碼問題,可以用單向廣度優先搜尋 雙向廣度優先搜尋 a 演算法 ida演算法解。用了雙向廣度優先搜尋和a 演算法解,在用a 演算法時,糾結了好幾天,後來在網上看了乙份部落格才發現自己錯在哪。之後解出來了。雖然做這題時很糾結,不過收穫真的很大,痛而快樂著 下面貼出用雙向廣度優先搜尋和a 演算...
A 搜尋演算法,poj1077 八數碼
今天看了a 搜尋演算法,聽說牛逼的很,不過關鍵還是在於它的評估函式,估計也不一定每題都能這麼容易想吧 就 來說吧,s,儲存所有所搜到的結點的資訊,包括空格位置,深度及評估值,這裡不給出h是因為h一直在變,b儲存開始結點資訊,visited儲存是否訪問到,接下來方向,答案,heap是為了提速而寫的堆實...
poj 1077 Eight A 解八數碼問題
題意 經典的八數碼問題。分析 搜尋演算法的區別是如何重排open表,關鍵是如何編碼狀態和定義狀態的值。對搜尋過程中任意狀態s,a 演算法以g s h s 重排open表,也就是說g s h s 是排列open中狀態的依據,其中g s 是初始狀態到s的消耗,h s 是s到目標狀態的估計。我重排open...