HDU 1043 Eight(康托展开)
来源:互联网 发布:linux创建逻辑卷命令 编辑:程序博客网 时间:2024/06/05 01:01
Eight
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 23953 Accepted Submission(s): 6400
Special Judge
Problem 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 1213 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 1213 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, several descriptions of configuration of the 8 puzzle. One 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
1 2 3
x 4 6
7 5 8
is described by this list:
1 2 3 x 4 6 7 5 8
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. Do not print a blank line between cases.
Sample Input
2 3 4 1 5 x 7 6 8
Sample Output
ullddrurdllurdruldr
Source
South Central USA 1998 (Sepcial Judge Module By JGShining)
Recommend
JGShining
题目大意:
超级经典的八数码问题。
一个九宫格上有一个空位,求移到初始状态的最短方案。
解题思路:
这题有很多写法,这里就利用康托展开保存状态来写了。
康托展开是对于全排列的一种效率非常高的可还原状压方式。对于n个数的全排列状态数为n!。
由于这题所有情况的终态相同,所以我们就可以从终态倒推出所有合法状态,存下来。然后就可以对于每个输入O(1)查询结果了。
AC代码:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <vector>#include <queue>#include <map>using namespace std;#define INF 0x3f3f3f3f#define mem(a,b) memset((a),(b),sizeof(a))const int MAXS=362880+3;//9!const int MAXN=9;const int sup[]={1,1,2,6,24,120,720,5040,40320};//阶乘表,用于康托展开int maze[MAXN];//保存棋盘状态的临时数组string s;char ans[MAXS];//从上一个状态走到当前状态的移动方向int path[MAXS];//走到的下一个状态queue<int> que;int init_id;//最终状态idint get_id()//康托展开{ int res=0; for(int i=0;i<9;++i) { int cnt=0;//剩下中第几小 for(int j=i+1;j<9;++j) if(maze[j]<maze[i]) ++cnt; res+=cnt*sup[8-i]; } return res;}void get_statue(int id)//通过康托逆展开生成状态{ int a[MAXN];//存剩下中第几小 bool used[MAXN];//是否已用 for(int i=8;i>=0;--i) { used[i]=false; a[8-i]=id/sup[i]; id%=sup[i]; } int cnt; for(int i=0;i<MAXN;++i) { cnt=0; for(int j=0;j<MAXN;++j) if(!used[j]) { if(cnt==a[i]) { maze[i]=j; used[j]=true; break; } else ++cnt; } }}void init()//bfs倒推预处理出所有结果{ mem(path,-1); for(int i=0;i<MAXN;++i) maze[i]=(i==8)?0:i+1; init_id=get_id(); que.push(init_id); while(!que.empty()) { int now=que.front(); que.pop(); get_statue(now); int p=-1;//x的位置 for(int i=0;i<MAXN;++i) if(maze[i]==0) p=i; if(p!=0&&p!=3&&p!=6)//x左移 { swap(maze[p],maze[p-1]); int next=get_id(); if(next!=init_id&&path[next]==-1)//新状态 { path[next]=now; ans[next]='r';//因为是倒推,所以方向反向 que.push(next); } swap(maze[p],maze[p-1]); } if(p!=2&&p!=5&&p!=8)//x右移 { swap(maze[p],maze[p+1]); int next=get_id(); if(next!=init_id&&path[next]==-1) { path[next]=now; ans[next]='l'; que.push(next); } swap(maze[p],maze[p+1]); } if(p<6)//x下移 { swap(maze[p],maze[p+3]); int next=get_id(); if(next!=init_id&&path[next]==-1) { path[next]=now; ans[next]='u'; que.push(next); } swap(maze[p],maze[p+3]); } if(p>2)//x上移 { swap(maze[p],maze[p-3]); int next=get_id(); if(next!=init_id&&path[next]==-1) { path[next]=now; ans[next]='d'; que.push(next); } swap(maze[p],maze[p-3]); } }}int main(){ init(); cin.sync_with_stdio(false);//取消流同步 while(getline(cin,s)) { int tmp=0; for(int i=0;i<s.length();++i) if(s[i]!=' ') if(s[i]=='x') maze[tmp++]=0; else maze[tmp++]=s[i]-'0'; int id=get_id(); if(id!=init_id&&path[id]==-1) cout<<"unsolvable"; while(path[id]!=-1) { cout<<ans[id]; id=path[id]; } cout<<'\n'; } return 0;}
阅读全文
0 0
- HDU 1043 Eight(康托展开)
- hdu 1043 eight (搜索 + 康托展开)
- [BFS+康托展开]Hdu 1043 Eight
- HDU 1043 Eight(bfs+康托展开)
- POJ 1077 Eight & HDU 1043 Eight(康托展开+BFS)
- HDU 1043 Eight A*算法+康托展开
- hdu 3567 Eight II (bfs+康托展开+预处理)
- HDU Eight II(BFS+康托展开)
- HDU 1043 Eight(广搜+哈希+康托展开+打表)
- hdu 1043 /poj 1077 Eight(经典八数码问题,BFS+康托展开)
- hdu 1043/poj 1077 Eight (八数码 经典搜索题 bfs + 康托展开)
- HDU 1043 Eight(反向BFS打表+康托展开)
- HDU ACM 1043 Eight->广度优先搜索(BFS)+康托展开(全排列hash)实践
- HDU 1043 Eight (BFS·八数码·康托展开)
- hdu 1043 Eight(bfs+康托)
- POJ 1077 Eight (正向BFS + 康托展开)
- hdu3567 Eight II(IDA*+康托展开)
- 【POJ1077】Eight-A*+康托展开
- 数字货币开发专题(区块链原理理解及应用实例)
- Java集合---HashMap源码剖析
- 2016华为校招机试题目02
- c++类
- 排序算法的稳定性问题
- HDU 1043 Eight(康托展开)
- (4)用记事本写Java程序HelloWorld,以及用控制台如何执行程序
- ios打包上传导致ERROR ITME-90205和ERROR ITME-90205错误的解决过程
- 基于反射实现通用的Excel读取文件
- 机器学习之numpy和matplotlib学习(十三)
- 最短路径:迪杰斯特拉算法
- Html5与Css3文本、图、标记(三)
- SkipList -----跳表
- Android新手入门,怎样才是正确的学习方式