题目类似于八数码,BFS+判重。
可以直接把16个数字当成二进制Hash。
#include <cstdio> #include <algorithm> #include <map> #include <queue> #define up(a,b,c) for(int c=a;c<=b;++c) #define down(a,b,c) for(int c=a;c>=b;--c) using namespace std; map<int,bool>vis; struct node{ int State[5][5]; int Code,Step; }Start,End; int fx[]={0,0,-1,0,1},fy[]={0,-1,0,1,0}; int Out; int MakeCode(node a){ //这里MakeCode是将16个数转化为2进制 //但是如果第一位是0 那么就无法进行了 0<<1 0<<2都是0啊 //所以前置增加一位数字1 也就是二进制是17位的 //不会爆int 因为1<<17最大也是就是13W左右 int Code=1; up(1,4,i){ up(1,4,j){ Code<<=1; if(a.State[i][j]) Code|=1; } } return Code; } bool Can(int x,int y){ if(x<1 || y<1 || x>4 || y>4) return false; return true; } void SWAP(int &a,int &b){ int c = a; a = b; b = c; } void BFS(){ if(Start.Code==End.Code) return; queue<node>Q; Q.push(Start); while( !Q.empty() ){ node now = Q.front(); now.Step++; Q.pop(); up(1,4,i){ up(1,4,j){ if(now.State[i][j]){ up(1,4,k){ int x = i+fx[k]; int y = j+fy[k]; if( Can(x,y) ){ SWAP(now.State[i][j],now.State[x][y]); int Code = MakeCode(now); if(Code==End.Code){ End.Step = now.Step; return; } if(!vis[Code]){ vis[Code]=1; Q.push(now); } SWAP(now.State[i][j],now.State[x][y]); } } } } } } } void init(){ char s[23]; up(1,4,i){ scanf("%s",s+1); up(1,4,j){ Start.State[i][j] = s[j]-'0'; } } Start.Step=0; int CODE = MakeCode(Start); // printf("开始:%d\n",CODE); Start.Code=CODE; vis[CODE]=1; up(1,4,i){ scanf("%s",s+1); up(1,4,j){ End.State[i][j] = s[j]-'0'; } } CODE = MakeCode(End); // printf("结束:%d\n",CODE); End.Code=CODE; vis[CODE]=1; } int main(){ init(); BFS(); printf("%d\n",End.Step); return 0; }