因为是计算还原成一种局面的最短步骤,应该想到从最终局面开始做bfs,把所有能到达的情况遍历一遍,把值存下来。
bfs过程中,访问过的局面的记录是此题的关键,9*9的方格在计算过程中直接存储非常占内存。而这个显然是12345678x的不同排列,考虑康拓展开来记录,每个局面hash成一个整数。步骤我先算了一下,最多有31步,我用4进制位hash成了两个整数来保存
#include <iostream> #include <iomanip> #include <set> #include <cmath> #include <string> #include <algorithm> #include <queue> #include <vector> #include <map> #define LL long long using namespace std; class cantor { public: #define siz 9 char c[siz]={'1','2','3','4','5','6','7','8','x'}; LL w[siz]; bool vis[siz]; cantor() { w[0]=1; for(int i=1;i<siz;i++) w[i]=w[i-1]*i; } void init() { for(int i=0;i<siz;i++) vis[i]=false; } LL makeCanto(string s) { init(); LL rec=0; for(int i=0;i<siz;i++) { int d=0; for(int j=0;j<siz;j++) { if(vis[j]) continue; if(c[j]!=s[i])d++; else { vis[j]=true; break; } } rec+=w[siz-i-1]*d; } return rec; } string recover(LL val) { init(); string s=""; for(int i=siz-1;i>=0;i--) { LL te=val/w[i]; val-=e*w[i]; for(int j=0,cnt=-1;j<siz;j++) { if(vis[j])continue; else cnt++; if(cnt==te&&!vis[j]) { s+=c[j]; vis[j]=true; break; } } } return s; } }; LL n,m; char mp[3][3]; set<LL> s; string ss=""; const string las="12345678x"; bool f; int dir[4][2]={-1,0,1,0,0,1,0,-1}; char dfuck[4]={'d','u','l','r'}; struct node { LL s; int c; int x,y; LL a,b; node(LL ss,int aa,int X,int Y,LL A,LL B){s=ss;c=aa;x=X;y=Y;a=A;b=B;} }; struct ax { LL a,b,c; ax(LL A,LL B,LL C){a=A;b=B;c=C;} ax(){} }; map<LL,ax> ans; LL bit[18]; int main() { cin.sync_with_stdio(false); cantor fx; bit[0]=1; for(int i=1;i<18;i++) bit[i]=bit[i-1]*4; queue<node> q; node ini=node(fx.makeCanto(las),0,2,2,0,0); q.push(ini); s.clear(); ans.clear(); int mx=0; s.insert(fx.makeCanto(las)); while(!q.empty()) { node now=q.front(); ans[now.s]=ax(now.a,now.b,now.c); q.pop(); mx=max(now.c,mx); for(int i=0;i<4;i++) { int yy=now.y+dir[i][0]; int xx=now.x+dir[i][1]; if(xx<0||yy<0||xx>=3||yy>=3)continue; string nx=fx.recover(now.s); swap(nx[now.y*3+now.x],nx[yy*3+xx]); LL nxv=fx.makeCanto(nx); if(s.find(nxv)!=s.end())continue; s.insert(nxv); LL na=now.a,nb=now.b; if(now.c<16) { na+=i*bit[now.c]; } else { nb+=i*bit[now.c-16]; } q.push(node(nxv,now.c+1,xx,yy,na,nb)); } } while(cin>>mp[0][0]>>mp[0][1]>>mp[0][2]>>mp[1][0]>>mp[1][1]>>mp[1][2]>>mp[2][0]>>mp[2][1]>>mp[2][2]) { int x,y; f=false; s.clear(); ss=""; for(int i=0;i<3;i++) for(int j=0;j<3;j++) { ss+=mp[i][j]; if(mp[i][j]=='x') y=i,x=j; } string o=""; if(ss=="12345678x") { cout<<"lr"<<endl; continue; } if(ans.find(fx.makeCanto(ss))==ans.end()) { cout<<"unsolvable"<<endl; continue; } ax fuck=ans[fx.makeCanto(ss)]; for(int i=0;i<fuck.c;i++) { if(i<16) { o+=dfuck[fuck.a%4]; fuck.a/=4; } else { o+=dfuck[fuck.b%4]; fuck.b/=4; } } reverse(o.begin(),o.end()); cout<<o<<endl; } }
。