洛谷P2578 [ZJOI2005]九數碼遊戲
阿新 • • 發佈:2018-12-14
搜尋好題!
一個有 神器 神奇操作的八數碼
直接逆向BFS,對於每種狀態,判重and記錄擴充套件到他的id,以及給他一個id,搜到輸入的局面後,倒序輸出就行了
程式碼
#include<queue> #include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; struct emm { int b[3][3],co,la,id; bool friend operator < (emm x,emm y) {return x.co>y.co;} }ad,no,t[1000500]; priority_queue<emm>q; int a[4][4],cnt; bool f[9][9][9][9][9][9][9][9]; inline void cha1() { ad=no; ad.b[1][0]=no.b[0][0];ad.b[2][0]=no.b[1][0]; ad.b[2][1]=no.b[2][0];ad.b[2][2]=no.b[2][1]; ad.b[1][2]=no.b[2][2];ad.b[0][2]=no.b[1][2]; ad.b[0][1]=no.b[0][2];ad.b[0][0]=no.b[0][1]; if (f[ad.b[0][0]][ad.b[0][1]][ad.b[0][2]][ad.b[1][0]][ad.b[1][1]][ad.b[1][2]][ad.b[2][0]][ad.b[2][1]]) return ; f[ad.b[0][0]][ad.b[0][1]][ad.b[0][2]][ad.b[1][0]][ad.b[1][1]][ad.b[1][2]][ad.b[2][0]][ad.b[2][1]]=1; ad.co=no.co+1;ad.la=no.id;ad.id=++cnt;t[cnt]=ad; return (void)(q.push(ad)); } inline void cha2() { ad=no; ad.b[1][2]=no.b[1][0];ad.b[1][0]=no.b[1][1];ad.b[1][1]=no.b[1][2]; if (f[ad.b[0][0]][ad.b[0][1]][ad.b[0][2]][ad.b[1][0]][ad.b[1][1]][ad.b[1][2]][ad.b[2][0]][ad.b[2][1]]) return ; f[ad.b[0][0]][ad.b[0][1]][ad.b[0][2]][ad.b[1][0]][ad.b[1][1]][ad.b[1][2]][ad.b[2][0]][ad.b[2][1]]=1; ad.co=no.co+1;ad.la=no.id;ad.id=++cnt;t[cnt]=ad; return (void)(q.push(ad)); } inline bool che() { for (int i=0;i<3;i++) for (int k=0;k<3;k++) if (a[i][k]!=no.b[i][k]) return 0;return 1; } inline void BFS() { for (int i=0;i<3;i++) for (int k=0;k<3;k++) no.b[i][k]=i*3+k; no.co=0;no.id=0;t[0]=no;q.push(no); while (q.size()) { no=q.top();q.pop(); if (che()) return (void)(cout<<no.co); cha2();cha1(); } return ; } signed main() { for (int i=0;i<3;i++) for (int k=0;k<3;k++) scanf("%d",&a[i][k]); BFS();int e=no.id;puts(""); while (1) { for (int i=0;i<3;i++) { for (int k=0;k<3;k++) cout<<t[e].b[i][k]<<" "; puts(""); } if (!e) break; puts("");e=t[e].la; } return 0; }