題意:
經典的八數碼問題。
分析:搜尋演算法的區別是如何重排open表,關鍵是如何編碼狀態和定義狀態的值。對搜尋過程中任意狀態s,a*演算法以g(s)+h(s)重排open表,也就是說g(s)+h(s)是排列open中狀態的依據,其中g(s)是初始狀態到s的消耗,h(s)是s到目標狀態的估計。我重排open用的是c++的優先佇列,擴充套件狀態s得到新的狀態ns,如果ns沒訪問過則直接將ns及其節點加入open。如果ns已經訪問過(在open或close中),則更新ns的g(s)和h(s),由於無法直接在優先佇列中進行更新,所以需要在外部用全域性陣列記錄各個狀態的g值,當某個狀態的g值要改變時重新加入包含這個狀態的節點,這樣有冗餘但不影響正確性,也是優先佇列優化dijkstra演算法的方法。關於啟發函式h(s),h(s)越大則佔g(s)+h(s)的比重越大,程式的速度也越快,當h(s)總小於實際到最終狀態的消耗時,演算法是能確定找到最優解的,否則能找到解但不一定能找到最優解(總消耗最少)。這題資料有問題,3*h(s)當啟發函式是不能保證找到走過步數(消耗)最小的解的。
**://poj 1077
//sep9
#include #include #include using namespace std;
const int maxn=500000;
const int aim=46233;
int fac=;
int vis[maxn],g[maxn];
int dirx=;
int diry=;
int goal_x=;
int goal_y=;
char word[8]="lrud";
struct node };
priority_queueopen;
string path;
int cantor(int s)
return sum;
}int h(int s)
return sum;
}int a_star(node start)
int x=cur.loc/3;
int y=cur.loc%3;
for(int i=0;i<4;++i)/*else if(vis[nxt.status]==1&&g[cur.status]+1g[cur]+1>=g[nxt]
// nxt.f=nxt.f-g[nxt.status]+g[cur.status]+1;//update nxt.status
// g[nxt.status]=g[cur.status]+1;
// nxt.path=nxt.path+word[i];
// open.push(nxt);
}*/} vis[cur.status]=1;
} return 0;
}int main()
else
ncur.s[i]=tmp[0]-'0';
} ncur.status=cantor(ncur.s);
g[ncur.status]=0;
ncur.f=h(ncur.s);
if(a_star(ncur))
cout<
POJ1077 Eight A 康托展開
題目大意 乙個3 3的棋盤上有8個格仔寫著1 8的數字,還有乙個空格,給定局面,要求給出乙個空格的移動序列,使得達到目標狀態 1 2 3 4 5 6 7 8 x 空格 做法 大名鼎鼎的八數碼問題.學習了a 演算法後,今天特意去試做了了下,居然過了,資料好水啊.題目中的狀態可以用0 8的全排列表示,可...
poj 1077 八數碼難題
終於自己ac了這道八數碼難題,用的方法是最最普通的單項bfs hash,這裡主要的難點在於如何儲存狀態,其實,在八數碼裡所有的狀態共有9!種 362880種,所以在每個轉台節點,我需要乙個char state 3 3 來記錄當前棋盤的狀態,用乙個int x,y來記錄當前x的位置,用char oper...
POJ1077 經典的八數碼問題
很經典的八數碼問題,可以用單向廣度優先搜尋 雙向廣度優先搜尋 a 演算法 ida演算法解。用了雙向廣度優先搜尋和a 演算法解,在用a 演算法時,糾結了好幾天,後來在網上看了乙份部落格才發現自己錯在哪。之後解出來了。雖然做這題時很糾結,不過收穫真的很大,痛而快樂著 下面貼出用雙向廣度優先搜尋和a 演算...