poj 1077 Eight A 解八數碼問題

2021-07-02 20:06:05 字數 1537 閱讀 3549

題意:

經典的八數碼問題。

分析:搜尋演算法的區別是如何重排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 演算...