八数码问题。
BFS+康托展开。康托用来判重。直接搜的的话会超时。需要预处理。
我就用结构体存了一个状态。
struct lx { int can;//当前状态的康托展开 int pcan;//上一状态的康托展开 int k;//移动方向 };
把所有的 181442 种状态存下来。排序,然后二分搜索。迭代寻找上一状态,直到初始的 0 。
开始写的时候估计康托逆展开有点问题,一直WA。重写之后就莫名其妙的1A了。
G++ 171ms
#include<cstdio> #include<cstring> #include<string> #include<queue> #include<algorithm> #include<map> #include<stack> #include<iostream> #include<list> #include<set> #include<cmath> #define INF 0x7fffffff #define eps 1e-8 #define LL long long #define PI 3.141592654 #define CLR(a,b) memset(a,b,sizeof(a)) #define FORi(n) for(int i=0;i<n;i++) #define FORj(n) for(int j=0;j<n;j++) #define FORk(n) for(int k=0;k<n;k++) #define debug puts("==fuck==") #define acfun std::ios::sync_with_stdio(false) #define SIZE 1000+10 using namespace std; struct lx { int can; int pcan; int k; }; int g[4][4]={{1,2,3},{4,5,6},{7,8,9}}; int fac[]={1,1,2,6,24,120,720,5040,40320}; int xx[]={0,0,-1,1}; int yy[]={1,-1,0,0}; lx q[200000]; //max = 181441 bool vis[500000]; //max = 362879 int n; int cantor() { int tmp[10],top=0,num=0; FORi(3) FORj(3) tmp[top++]=g[i][j]; FORi(top) { int t=0; for(int j=i+1;j<top;j++) if(tmp[j]<tmp[i])t++; num+=fac[top-i-1]*t; } return num; } int uncantor(int num) { int tmp[10],top=0; bool v[10]; CLR(v,0); for(int i=1;i<=9;i++) { int t=num/fac[9-i]; num-=t*fac[9-i]; int j=1,k=0; for(;k<=t;j++) if(!v[j])k++; j--; v[j]=1; tmp[i-1]=j; } int k=0,site; FORi(3) FORj(3) { g[i][j]=tmp[k++]; if(g[i][j]==9)site=i*3+j; } return site; } void bfs() { int h=0,e=0; q[h].can=cantor(); q[h].pcan=-1; q[h++].k=-1; CLR(vis,0); vis[0]=1; while(e<h) { int can=q[e++].can; int site=uncantor(can); int i=site/3; int j=site%3; for(int k=0; k<4; k++) { int x=i+xx[k]; int y=j+yy[k]; if(x>=3||x<0||y>=3||y<0)continue; swap(g[i][j],g[x][y]); int tmp=cantor(); swap(g[i][j],g[x][y]); if(vis[tmp])continue; vis[tmp]=1; q[h].can=tmp; q[h].pcan=can; q[h++].k=k; n=h; } } } bool cmp(lx a,lx b) { return a.can<b.can; } int half(int left,int right,int key) { int l=left,r=right; while(l<r) { int m=(l+r)>>1; if(q[m].can==key)return m; else if(q[m].can>key)r=m; else l=m+1; } return -2; } int main() { bfs(); sort(q,q+n,cmp); char str[11]; while(~scanf("%s",str)) { if(str[0]>='0'&&str[0]<='8') g[0][0]=str[0]-'0'; else g[0][0]=9; for(int i=1; i<9; i++) { scanf("%s",str); if(str[0]>='0'&&str[0]<='8') g[i/3][i%3]=str[0]-'0'; else g[i/3][i%3]=9; } int can=cantor(); char out[1001]; int top=0; bool flag=0; while(can!=-1) { int k=half(0,n,can); if(k==-2) { flag=1; break; } if(q[k].k==0) out[top++]='l'; else if(q[k].k==1) out[top++]='r'; else if(q[k].k==2) out[top++]='d'; else out[top++]='u'; can=q[k].pcan; } if(flag) puts("unsolvable"); else { out[top-1]='\0'; puts(out); } } }
原文地址:http://blog.csdn.net/dongshimou/article/details/39319895