FZU 2180 騎士 (雙向BFS)
阿新 • • 發佈:2019-02-01
#include<stdio.h> #include<string.h> #include<map> #include<queue> #include<algorithm> #define inf 1e8 using namespace std; char a[10][10]={"11111","01111","00*11","00001","00000"}; char b[10][10]; int state1,pos1,state2,pos2; struct node { int state;///圖中“1”分佈的狀態 int pos;///“*”的位置編號 int dis;///步數 }; int id[10][10];///記錄個點編號 const int f[8][2]={1,-2,1,2,2,1,2,-1,-1,2,-1,-2,-2,1,-2,-1}; int bfs() { queue<node> q1,q2; map<pair<int,int>,int> m1,m2;///map對映的是步數 pair<int,int> p1,p2; node now1,next1; node now2,next2; ///正向 now1.state=state1; now1.pos=pos1; now1.dis=1; q1.push(now1); p1=make_pair(state1,pos1); m1[p1]=1; ///逆向 now2.state=state2; now2.pos=pos2; now2.dis=1; q2.push(now2); p2=make_pair(state2,pos2); m2[p2]=1; if(state1==state2&&pos1==pos2) return 0;///一開始就是答案,輸出0 while(q1.size()&&q2.size()) { ///正向 now1=q1.front(); q1.pop(); if(now1.dis>=9) return -1; int x,y;///將pos還原成座標 x=now1.pos/5; y=now1.pos%5; for(int i=0;i<8;i++) { int mx=x+f[i][0]; int my=y+f[i][1]; if(mx<0||mx>=5||my<0||my>=5) continue; ///接下來將‘*’與(mx,my)處的值交換 next1.pos=id[mx][my]; next1.dis=now1.dis+1; next1.state=now1.state;///暫且存下來等待交換 if(now1.state&(1<<id[mx][my]))///該位置為1(為0就不管state,因為不會改變圖中“1”的分佈情況) { next1.state|=(1<<id[x][y]);///將1交換到(x,y)處 next1.state^=(1<<id[mx][my]);///由於(mx,my)處被換成了‘*’,所以該地方的1要清掉 } p1=make_pair(next1.state,next1.pos); if(m1.find(p1)==m1.end())///用find高效很多,如果該處寫成if(!m1[p1]) 會慢很多,因為map非法查詢會多記憶體,會變很慢 { if(m2.find(p1)!=m2.end()) return next1.dis+m2[p1]-2; m1[p1]=next1.dis; q1.push(next1); } } ///逆向 now2=q2.front(); q2.pop(); if(now2.dis>=8) return -1; x=now2.pos/5; y=now2.pos%5; for(int i=0;i<8;i++) { int mx=x+f[i][0]; int my=y+f[i][1]; if(mx<0||mx>=5||my<0||my>=5) continue; next2.pos=id[mx][my]; next2.dis=now2.dis+1; next2.state=now2.state; if(now2.state&(1<<id[mx][my])) { next2.state|=(1<<id[x][y]); next2.state^=(1<<id[mx][my]); } p2=make_pair(next2.state,next2.pos); if(m2.find(p2)==m2.end()) { if(m1.find(p2)!=m1.end()) return next2.dis+m1[p2]-2; m2[p2]=next2.dis; q2.push(next2); } } } return -1; } void init() { int num=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) id[i][j]=num++; state1=0; for(int i=0;i<5;i++) for(int j=0;j<5;j++) { if(a[i][j]=='1') state1|=(1<<id[i][j]); if(a[i][j]=='*') pos1=id[i][j]; } } int main() { init();///初始的圖是不會變的,預先處理就行 int T; scanf("%d",&T); while(T--) { state2=0; for(int i=0;i<5;i++) { scanf("%s",b[i]); for(int j=0;j<5;j++) { if(b[i][j]=='1') state2|=(1<<id[i][j]); if(b[i][j]=='*') pos2=id[i][j]; } } int res=bfs(); if(res==-1||res>15) puts("Bored!"); else printf("%d\n",res); } return 0; }