Eight
Time Limit: 1000MS | Memory Limit: 65536K | |||
Total Submissions: 24515 | Accepted: 10812 | Special Judge |
Description
The 15-puzzle has been around for over 100 years; even if you don't know it by that name, you've seen it. It is constructed with 15 sliding tiles, each with a number from 1 to 15 on it, and all packed into a 4 by 4 frame with one tile missing. Let's call the missing tile 'x'; the object of the puzzle is to arrange the tiles so that they are ordered as:
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x
where the only legal operation is to exchange 'x' with one of the tiles with which it shares an edge. As an example, the following sequence of moves solves a slightly scrambled puzzle:
1 2 3 4 1 2 3 4 1 2 3 4 1 2 3 4 5 6 7 8 5 6 7 8 5 6 7 8 5 6 7 8 9 x 10 12 9 10 x 12 9 10 11 12 9 10 11 12 13 14 11 15 13 14 11 15 13 14 x 15 13 14 15 x r-> d-> r->
The letters in the previous row indicate which neighbor of the 'x' tile is swapped with the 'x' tile at each step; legal values are 'r','l','u' and 'd', for right, left, up, and down, respectively.
Not all puzzles can be solved; in 1870, a man named Sam Loyd was famous for distributing an unsolvable version of the puzzle, and
frustrating many people. In fact, all you have to do to make a regular puzzle into an unsolvable one is to swap two tiles (not counting the missing 'x' tile, of course).
In this problem, you will write a program for solving the less well-known 8-puzzle, composed of tiles on a three by three
arrangement.
Input
You will receive a description of a configuration of the 8 puzzle. The description is just a list of the tiles in their initial positions, with the rows listed from top to bottom, and the tiles listed from left to right within a row, where the tiles are represented by numbers 1 to 8, plus 'x'. For example, this puzzle
is described by this list:
1 2 3 x 4 6 7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
Output
You will print to standard output either the word ``unsolvable'', if the puzzle has no solution, or a string consisting entirely of the letters 'r', 'l', 'u' and 'd' that describes a series of moves that produce a solution. The string should include no spaces and start at the beginning of the line.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
解决方案:用bfs+字符串哈希靠rp能过,bfs+全排列哈希完全没问题,双向bfs+字符串哈希rp不够,过不了,双向bfs+全排列哈希也没问题,所以全排列哈希比字符串哈希靠谱。这些只能过了POJ上的题,hdu上的还是超时了。
code:bfs+字符串哈希/全排列哈希
#include<iostream> #include<cstdio> #include<cstring> #include<queue> #include<stack> #include<map> using namespace std; char M[20]; int dirx[4]= {1,-1,0,0}; int diry[4]= {0,0,-1,1}; char op[6]="dulr"; char goal[20]="12345678x"; int fact[8]= {1,2,6,24,120,720,5040,40320}; struct path { char op; int fa; } P[600000];///¼Ç¼·¾¶ char Path[600000];///¼Ç¼²Ù×÷ bool vis[600011]; struct node { char M[20]; int position; int op; node(char s[],int p,int o) { for(int i=0; i<9; i++) M[i]=s[i]; M[9]='\0'; position=p; op=o; } void Swap(int s,int e) { char temp=M[s]; M[s]=M[e]; M[e]=temp; position=s; } }; bool judge(char edf[]) { for(int i=0; i<9; i++) { if(edf[i]==goal[i]) { } else return false; } return true; } unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF)%600007; }///字符串哈希 int code(char s[]) { int res=0; for(int i=1; i<9; i++) { int cnt=0; for(int j=0; j<i; j++) { if(s[j]>s[i]) cnt++; } cnt*=fact[i-1]; res+=cnt; } return res; }///全排列哈希 int main() { while(~scanf(" %c",&M[0])) { int p; if(M[0]=='x') p=0; for(int i=1; i<9; i++) { scanf(" %c",&M[i]); if(M[i]=='x') p=i; } M[9]='\0'; getchar(); memset(vis,false,sizeof(vis)); node temp(M,p,1); queue<node >Q; Q.push(temp); int times=1; bool flag=false; vis[code(M)]=true; while(!Q.empty()) { temp=Q.front(); Q.pop(); if(judge(temp.M)) { int j=0; int s=temp.op; while(s!=1) { Path[j++]=P[s].op; s=P[s].fa; } Path[j]='\0'; flag=true; break; } int x=temp.position/3,y=temp.position%3; for(int i=0; i<4; i++) { int xx=x+dirx[i]; int yy=y+diry[i]; if(xx>=0&&xx<=2&&yy>=0&&yy<=2) { int p=3*xx+yy; if(p>=0&&p<=8) { node temp1=temp; temp1.Swap(p,temp.position); int e=code(temp1.M); if(!vis[e]) { vis[e]=true;; P[++times].fa=temp.op; P[times].op=op[i]; temp1.op=times; Q.push(temp1); } } } } } if(flag) { int len=strlen(Path); for(int i=len-1; i>=0; i--) { printf("%c",Path[i]); } printf("\n"); } else { printf("unsolvable\n"); } } return 0; }
code:双dfs+全排列哈希
#include<cstdio> #include<cstring> #include<queue> #include<map> #include<iostream> using namespace std; struct node { char M[20]; int position; node(char s[],int p) { for(int i=0; i<9; i++) { M[i]=s[i]; } M[9]='\0'; position=p; } void Swap(int e,int p) { char temp=M[e]; M[e]=M[p]; M[p]=temp; position=e; } }; int dirx[4]= {1,-1,0,0}; int diry[4]= {0,0,-1,1}; char O[5]="dulr"; char inO[5]="udrl"; int fact[8]={1,2,6,24,120,720,5040,40320}; unsigned int BKDRHash(char *str) { unsigned int seed = 131; // 31 131 1313 13131 131313 etc.. unsigned int hash = 0; while (*str) { hash = hash * seed + (*str++); } return (hash & 0x7FFFFFFF)%600013; }///字符串哈希 int code(char s[]){ int res=0; for(int i=1;i<9;i++){ int cnt=0; for(int j=0;j<i;j++){ if(s[j]>s[i]) cnt++; } cnt*=fact[i-1]; res+=cnt; } return res; }///全排列哈希 int vis[600013]; struct node1 { int fa; char op; } Op[600013]; void init() { memset(vis,0,sizeof(vis)); for(int i=0; i<600013; i++) { Op[i].fa=-1; } } bool judge(node temp) { node endpoint("12345678x",8); for(int i=0; i<9; i++) { if(temp.M[i]!=endpoint.M[i]) return false; } return true; } char path[600011]; char path1[600011]; int main() { char M[20]; while(~scanf(" %c",&M[0])) { int p; if(M[0]=='x')p=0; for(int i=1; i<9; i++) { scanf(" %c",&M[i]); if(M[i]=='x') p=i; } getchar(); M[9]='\0'; init(); node start(M,p); node endpoint("12345678x",8); queue<node>Q1,Q2; int e1=code(M),e2=code(endpoint.M); vis[e1]=1,vis[e2]=2; Q1.push(start); Q2.push(endpoint); bool flag=false; while(!Q1.empty()&&!Q2.empty()) { node temp=Q1.front(); Q1.pop(); if(judge(temp)) { //cout<<"sdf"; int e=BKDRHash(temp.M); int j=0; while(Op[e].fa!=-1) { path[j++]=Op[e].op; e=Op[e].fa; } path[j]='\0'; path1[0]='\0'; flag=true; break; } int x=temp.position/3,y=temp.position%3; for(int i=0; i<4; i++) { int xx=x+dirx[i]; int yy=y+diry[i]; if(xx>=0&&xx<=2&&yy>=0&&yy<=2) { int newp=xx*3+yy; if(newp>=0&&newp<=8) { node temp1=temp; temp1.Swap(newp,temp.position); int e=code(temp1.M); int efa=code(temp.M); if(!vis[e]) { vis[e]=1; Op[e].fa=efa; Op[e].op=O[i]; Q1.push(temp1); } else if(vis[e]==2) { int j=0,k=0; path[j++]=O[i]; while(Op[efa].fa!=-1) { path[j++]=Op[efa].op; efa=Op[efa].fa; } path[j]='\0'; while(Op[e].fa!=-1) { path1[k++]=Op[e].op; e=Op[e].fa; } path1[k]='\0'; flag=true; break ; } } } } if(flag) break; temp=Q2.front(); Q2.pop(); x=temp.position/3,y=temp.position%3; for(int i=0; i<4; i++) { int xx=x+dirx[i]; int yy=y+diry[i]; if(xx>=0&&xx<=2&&yy>=0&&yy<=2) { int newp=xx*3+yy; if(newp>=0&&newp<=8) { node temp1=temp; temp1.Swap(newp,temp.position); int e=code(temp1.M); int efa=code(temp.M); if(!vis[e]) { vis[e]=2; Op[e].fa=efa; Op[e].op=inO[i]; Q2.push(temp1); } else if(vis[e]==1) { int j=0,k=0; path1[k++]=inO[i]; while(Op[efa].fa!=-1) { path1[k++]=Op[efa].op; efa=Op[efa].fa; } path1[k]='\0'; while(Op[e].fa!=-1) { path[j++]=Op[e].op; e=Op[e].fa; } path[j]='\0'; flag=true; break ; } } } } if(flag) break; } if(flag) { int len2=strlen(path); for(int i=len2-1; i>=0; i--) { printf("%c",path[i]); } printf("%s\n",path1); } else { printf("unsolvable\n"); } } return 0; }