poj1077Eight
来源:互联网 发布:崩坏3rd矩阵空间 编辑:程序博客网 时间:2024/04/30 02:31
Eight
Time Limit: 1000MS Memory Limit: 65536KTotal Submissions: 21880 Accepted: 9674 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
Source
South Central USA 1998
今天做了一下人人都是说是很经典的题目,poj1077Eight。。。
其实这道题目并不是很难。关键是在BFS时如何设置标志数组,如果是最容易想到的是vist[][][][][][][][][]设置一个九维数组。。。。
我一想到这个我就知道着一定超内存了。。。
其实一想也没有那么多的变化。。。
是9的全排列9!= 362 880种 。。
所以上网找资料就找到了康拓展开。。。。
我最记得是在2013广东省“有为杯”ACM程序大赛热身时有过这类题。。。
用康拓展开成hash函数。。。
#include<stdio.h>#include<string.h>#include<stdlib.h>int hash[363000];int fact[9] = {1,1,2,6,24,120,720,5040,40320};char finishPath[1001];struct queue{ int map[9]; int x_place; char dir; int last; int hashvalue;}queue[363000]; int m_hash(int m[]){ int vist[10]={0},sum = 0,num; for(int i=0;i<9;i++) { num = 0; for(int j=1;j<m[i];j++)if(vist[j] == 0)num++;vist[m[i]] = 1;sum+=num*fact[8-i]; } return sum;} int BFS(){ int head = 0,tail = 1; int s,q_map[9]; int q_x,q_hash,tem; while(head < tail) { s = head++; if(queue[s].hashvalue == 0)return s; for(int i=0;i<9;i++) //将map[]的 值先放入暂时数组q_map[]中 q_map[i] = queue[s].map[i]; q_x = queue[s].x_place-3; //用q_x保存 x 点上下左右的点 if(q_x>=0 && q_x < 9 ) //x 的上点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++)queue[tail].map[i] = q_map[i]; queue[tail].dir = 'u'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } q_x = queue[s].x_place-1;if(q_x!=2 && q_x!=5 && q_x!=-1 ) // x 的左点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++)queue[tail].map[i] = q_map[i]; queue[tail].dir = 'l'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; }q_x = queue[s].x_place+3;if(q_x>=0 && q_x < 9 ) // x 的下点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++)queue[tail].map[i] = q_map[i]; queue[tail].dir = 'd'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } q_x = queue[s].x_place+1;if(q_x!=3 && q_x!=6 && q_x!=9 ) // x 的右点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++)queue[tail].map[i] = q_map[i]; queue[tail].dir = 'r'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } } //while return -1;} int main(){ char ch[4]; for(int j=0;j<9;j++){scanf("%s",ch); if(ch[0]!='x')queue[0].map[j] = ch[0]-'0'; else { queue[0].dir = '\0'; queue[0].last = -1; queue[0].x_place = j; queue[0].map[j] = 9; } }queue[0].hashvalue = m_hash(queue[0].map); hash[queue[0].hashvalue] = 1; int Finish = BFS();if(Finish != -1){int F = Finish,t=0;memset(finishPath,0,sizeof(finishPath));while(queue[F].dir != '\0'){finishPath[t++] = queue[F].dir;F = queue[F].last;} finishPath[t] = '\0';for(t=t-1;t>=0;t--) printf("%c",finishPath[t]);printf("\n");}else printf("unsolvable\n"); system("pause");return 0;}
不过可惜在杭电上超时~~~
因为杭电上是多组数据。。。
如果将上面的程序简单地改成多组输入将会超时。。。
所以需要用打表的方式来存会快很多。。。。
而且还要BFS的反向搜索。。
#include<stdio.h>#include<string.h>#include<stdlib.h>int hash[363000];int mhash[363000]; //用来存哈希值时的对应的队列下标int fact[9] = {1,1,2,6,24,120,720,5040,40320};char finishPath[1001];struct queue{ int map[9]; int x_place; char dir; int last; int hashvalue;}queue[363000]; int m_hash(int m[]){ int vist[10]={0},sum = 0,num; for(int i=0;i<9;i++) { num = 0; for(int j=1;j<m[i];j++) if(vist[j] == 0) num++; vist[m[i]] = 1; sum+=num*fact[8-i]; } return sum;} void BFS(){ int head = 0,tail = 1; int s,q_map[9]; int q_x,q_hash,tem; while(head < tail) { s = head++; mhash[queue[s].hashvalue] = s; for(int i=0;i<9;i++) //将map[]的 值先放入暂时数组q_map[]中 q_map[i] = queue[s].map[i]; q_x = queue[s].x_place-3; //用q_x保存 x 点上下左右的点 if(q_x>=0 && q_x < 9 ) //x 的上点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++) queue[tail].map[i] = q_map[i]; queue[tail].dir = 'd'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } q_x = queue[s].x_place-1; if(q_x!=2 && q_x!=5 && q_x!=-1 ) // x 的左点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++) queue[tail].map[i] = q_map[i]; queue[tail].dir = 'r'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } q_x = queue[s].x_place+3; if(q_x>=0 && q_x < 9 ) // x 的下点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++) queue[tail].map[i] = q_map[i]; queue[tail].dir = 'u'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } q_x = queue[s].x_place+1; if(q_x!=3 && q_x!=6 && q_x!=9 ) // x 的右点 { tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; q_hash = m_hash(q_map); if(hash[q_hash] == 0) { for(int i=0;i<9;i++) queue[tail].map[i] = q_map[i]; queue[tail].dir = 'l'; queue[tail].hashvalue = q_hash; queue[tail].last = s; queue[tail++].x_place = q_x; hash[q_hash] = 1; } tem = q_map[queue[s].x_place]; q_map[queue[s].x_place] = q_map[q_x]; q_map[q_x] =tem; } } //while } int main(){ for(int i=0;i<9;i++) queue[0].map[i] = i+1; queue[0].dir = '\0'; queue[0].last = -1; queue[0].x_place = 8; queue[0].hashvalue = 0; memset(mhash,0,sizeof(mhash)); BFS(); char ch[4]; int mmap[10],hvalue; while(scanf("%s",ch)!=EOF) { if(ch[0]!='x') mmap[0] = ch[0]-'0'; else mmap[0] = 9; for(int j=1;j<9;j++) { scanf("%s",ch); if(ch[0]!='x') mmap[j] = ch[0]-'0'; else mmap[j] = 9; } hvalue = m_hash(mmap); if(hvalue != 0) { if(mhash[hvalue]) { memset(finishPath,0,sizeof(finishPath)); int F = mhash[hvalue]; while(queue[F].dir != '\0') { printf("%c",queue[F].dir); F = queue[F].last; } printf("\n"); } else printf("unsolvable\n"); } else printf("\n"); } system("pause"); return 0;}