UESTC1490 Eight Puzzle 双向BFS

    技术2022-05-12  8

    Eight Puzzle

     

    Time Limit: 2000 ms Memory Limit: 65536 kB Solved: 35 Tried: 665

     

    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: 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. To simplify this problem, you should print the minimum steps only.

     

    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 puzzle1 2 3x 4 67 5 8is 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.Otherwise, output an integer which equals the minimum steps. If

     

    Sample Input 1 2 x 4 5 3 7 8 6

     

    Sample Output 2

     

    Hint Any violent algorithm may gain TLE. So a smart method is expected. The data used in this problem is unofficial data prepared by hzhua. So any mistake here does not imply mistake in the offcial judge data.

     

    Source modified from South Central USA 1998 140次后终于AC。。。 原来这题求最少步数不能用A*,杯具。。。 只好用双向BFS #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> using namespace std; char hash1[362885],hash2[362885]; int b[9]={1,1,2,6,24,120,720,5040,40320},d[4][2]={-1,0,1,0,0,-1,0,1}; struct node { int p,n; int num[9]; node(int pp,int nn,int *a){for(p=0;p<9;p++)num[p]=a[p];p=pp;n=nn;} }; int fun(int *a) { int i,j,s=0; for(i=0;i<9;i++) for(j=i+1;j<9;j++) if(a[j]&&a[i]>a[j]) s++; return s; } bool ok(int *a) { int i; for(i=0;i<9;i++) if(a[i]!=(i+1)%9) return 0; return 1; } int Hash(int *num) { int i,j,k,h=0; for(i=0;i<9;i++) { for(k=0,j=i+1;j<9;j++) if(num[i]>num[j]) k++; h+=k*b[num[i]]; } return h; } void bfs(node st) { int i,x,y,p,n,h,num[9]; queue<node> q1,q2; q1.push(st); for(i=0;i<9;i++) num[i]=(i+1)%9; q2.push(node(8,0,num)); hash2[Hash(num)]=0; while(q1.size()&&q2.size()) { if(q1.size()) { node t=q1.front(); q1.pop(); n=t.n+1; p=t.p; for(i=0;i<4;i++) { x=p/3+d[i][0]; y=p%3+d[i][1]; if(x>=0&&y>=0&&x<3&&y<3) { swap(t.num[p],t.num[x*3+y]); if(hash2[h=Hash(t.num)]!=-1) { printf("%d/n",n+hash2[h]); return; } if(hash1[h]==-1) { hash1[h]=n; q1.push(node(x*3+y,n,t.num)); } swap(t.num[p],t.num[x*3+y]); } } } if(q2.size()) { node t=q2.front(); q2.pop(); n=t.n+1; p=t.p; for(i=0;i<4;i++) { x=p/3+d[i][0]; y=p%3+d[i][1]; if(x>=0&&y>=0&&x<3&&y<3) { swap(t.num[p],t.num[x*3+y]); if(hash1[h=Hash(t.num)]!=-1) { printf("%d/n",n+hash1[h]); return; } if(hash2[h]==-1) { hash2[h]=n; q2.push(node(x*3+y,n,t.num)); } swap(t.num[p],t.num[x*3+y]); } } } } puts("unsolvable"); } int main() { int num[9],i,j,k; char c,s[25]; while(gets(s)) { for(i=j=0;i<9;i++,j++) { while(sscanf(s+j,"%c",&c),c==' ')j++; if(c=='x') num[k=i]=0; else num[i]=c-'0'; } if((fun(num)&1)) puts("unsolvable"); else { if(ok(num)) { puts("0"); continue; } memset(hash1,-1,sizeof(hash1)); memset(hash2,-1,sizeof(hash2)); hash1[Hash(num)]=0; bfs(node(k,0,num)); } } } #include<cstdio> #include<cstdlib> #include<cstring> #include<queue> #include<algorithm> using namespace std; char hash1[362885],hash2[362885]; int b[9]={1,1,2,6,24,120,720,5040,40320},d[4][2]={-1,0,1,0,0,-1,0,1}; struct node { int p,n; char num[9]; node(int pp,int nn,char *a){for(p=0;p<9;p++)num[p]=a[p];p=pp;n=nn;} }; int fun(char *a) { int i,j,s=0; for(i=0;i<9;i++) for(j=i+1;j<9;j++) if(a[j]&&a[i]>a[j]) s++; return s; } bool ok(char *a) { for(int i=0;i<9;i++) if(a[i]!=(i+1)%9) return 0; return 1; } int Hash(char *num) { int i,j,k,h=0; for(i=0;i<9;i++) { for(k=0,j=i+1;j<9;j++) if(num[i]>num[j]) k++; h+=k*b[num[i]]; } return h; } int ex(queue<node>& q,char *h1,char *h2) { int i,x,y,p,n,h; node t=q.front(); q.pop(); n=t.n+1; p=t.p; for(i=0;i<4;i++) { x=p/3+d[i][0]; y=p%3+d[i][1]; if(x>=0&&y>=0&&x<3&&y<3) { swap(t.num[p],t.num[x*3+y]); if(h2[h=Hash(t.num)]!=-1) { printf("%d/n",n+h2[h]); return 1; } if(h1[h]==-1) { h1[h]=n; q.push(node(x*3+y,n,t.num)); } swap(t.num[p],t.num[x*3+y]); } } return 0; } void bfs(node st) { char num[9]; queue<node> q1,q2; q1.push(st); for(int i=0;i<9;i++) num[i]=(i+1)%9; q2.push(node(8,0,num)); hash2[Hash(num)]=0; while(q1.size()&&q2.size()) if(q1.size()&&ex(q1,hash1,hash2)||q2.size()&&ex(q2,hash2,hash1)) return; puts("unsolvable"); } int main() { int i,j,k; char c,num[9],s[25]; while(gets(s)) { for(i=j=0;i<9;i++,j++) { while(sscanf(s+j,"%c",&c),c==' ')j++; if(c=='x') num[k=i]=0; else num[i]=c-'0'; } if((fun(num)&1)) puts("unsolvable"); else { if(ok(num)) { puts("0"); continue; } memset(hash1,-1,sizeof(hash1)); memset(hash2,-1,sizeof(hash2)); hash1[Hash(num)]=0; bfs(node(k,0,num)); } } }

    最新回复(0)