HDU1043 eight 八数码问题
来源:互联网 发布:js清除input的value值 编辑:程序博客网 时间:2024/05/16 06:24
八数码问题:
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
本题有多种答案,采用special judge
注意:如何判断给出的序列无解.
可以序列的逆序对进行剪枝。对于 x,如果在所在行移动,逆序数对不变,如果在列上移动,逆序数对成偶数加减,那么逆序对必须为even。(偶数)
我设置两个队列,采用双向广搜的方法,poj 79ms.
下面附代码:
#include <iostream>#include <map>#include <cstdio>using namespace std;#define M 500000struct state{ int father,code; char dir;};state que[M],reque[M];char path[M];// 答案数组void codes(int code){ char s[10]; sprintf(s,"%d",code); for(int i=0;i<9;i++) { if(i!=0&& i%3==0) printf("\n"); printf("%c ",s[i]); } printf("\n\n");}int main(){ int dir[4][2]= {{-1,0},{1,0},{0,-1},{0,1}}; //方向数组 char str[4]={'u','d','l','r'}; char str1[4]={'d','u','r','l'}; int base[9]= {100000000,10000000,1000000,100000,10000,1000,100,10,1}; map<int,int> a; char w[3][3],w1[9]; int i,j,counter,qhead,qrear,re_qhead,re_qrear,ji,ji1,x,y,k; int newx,newy; while(cin>>w[0][0]){cin>>w[0][1]>>w[0][2];w1[0]=w[0][0];w1[1]=w[0][1];w1[2]=w[0][2];for(i=1;i<3;i++)for(j=0;j<3;j++){ cin>>w[i][j]; w1[i*3+j]=w[i][j];// convert to one array} //求逆序对数 counter=0; for(i=0; i<8; ++i) for(j=i+1; j<9; ++j) if(w1[i]!='x'&&w1[j]!='x'&&w1[i]>w1[j]) counter++; //如果逆序对数是 奇数,那么无法转化为目标状态 if(counter&1) { printf("unsolveble!\n"); } else { int e,s; s=0; e=123456789;//反向搜索的起始状态 //将八数码转换为一个整数s; for(i=0; i<9; i++) { if(w1[i]=='x') s=s*10+9; else s=s*10+(w1[i]-'0'); } //init qhead=qrear=re_qhead=re_qrear=1; que[qrear].code=s; //队列1 reque[re_qrear].code=e;//队列2 a[s]=1;//正向搜索 已访问 标记为1 a[e]=2;//反向搜索 已访问 标记为2 bool flag=0; if(s==e)//特殊情况处理 flag=1; while(!flag) { for(ji=0; ji<9; ji++) //提取正着搜时x所在的位置 if((que[qhead].code/base[ji])%10==9) break; for(ji1=0; ji1<9; ji1++) //提取反着搜时x所在的位置 if((reque[re_qhead].code/base[ji1])%10==9) break; for(i=0; i<4; i++) //双向广搜 { x=ji/3; y=ji%3; newx=x+dir[i][0]; newy=y+dir[i][1]; if(newx<3&&newx>=0&&newy<3&&newy>=0&&flag==0) { s=que[qhead].code;//s为当前的code //求新的code int d1=9;//d1=(s/base[ji])%10;//可以直接赋值为9 int d2=(s/base[newx*3+newy])%10;//与之交换的数放在d2中 s=s-d1*base[ji] - d2*base[newx*3+newy]; s=s+d1*base[newx*3 + newy]+d2*base[ji]; if(a[s]!=1) { if(a[s]==2) flag=1;//搜到了 a[s]=1;//标记 qrear++; que[qrear].code=s; que[qrear].father=qhead;//记录该节点是由哪个节点扩展来的 que[qrear].dir=str[i];//标记方向 } } x=ji1/3; y=ji1%3; newx=x+dir[i][0]; newy=y+dir[i][1]; if(newx<3&&newx>=0&&newy<3&&newy>=0&&flag==0) { s=reque[re_qhead].code;//找到新的S //求新的code int d1=9;//d1=(s/base[ji1])%10;//可以直接赋值为9 int d2=(s/base[newx*3+newy])%10;//与之交换的数放在d2中 s=s-d1*base[ji1] - d2*base[newx*3+newy]; s=s+d1*base[newx*3 + newy]+d2*base[ji1]; if(a[s]==0) { a[s]=2;//标记 re_qrear++; reque[re_qrear].code=s; reque[re_qrear].father=re_qhead;//记录该节点是由哪个节点扩展来的 reque[re_qrear].dir=str1[i];//标记方向 } } } qhead++;//从队列1中取下一个节点 re_qhead++;//从队列2 中取下一个节点 }//end while //下面提取路径 counter=0; k=qrear; //printf("%d\n",que[qrear].code); //codes(que[qrear].code); while(k!=1) { path[counter++]=que[k].dir; k=que[k].father; } for(i=counter-1;i>=0;i--) printf("%c",path[i]); // printf("\nup is first\n"); k=1;counter=0; while(k<=re_qrear&&reque[k].code!=que[qrear].code) { k++; } //printf("%d\n",reque[reque[k].father].code); while(k!=1) { path[counter++]=reque[k].dir; k=reque[k].father; // codes(reque[k].code); } for(i=0;i<counter;i++) printf("%c",path[i]); printf("\n"); a.clear(); }} return 0;}/**2 3 41 5 x7 6 81 2 34 5 67 8 x*/
- HDU1043 eight 八数码问题
- HDU1043 Eight 八数码问题
- poj1077 hdu1043 Eight 八数码问题
- hdu1043 Eight (八数码问题,多种解法)
- POJ1077、HDU1043 Eight 八数码问题:双向BFS、A*
- hdu1043 八数码问题
- POJ1077 HDU1043 Eight 八数码 (A*+康托展开)
- Poj1077/HDU1043(A*搜索)八数码问题
- hdu1043八数码问题解题报告
- 八数码与IDA*问题 HDU1043&&POJ1077
- 1077 Eight 八数码问题
- hdu1043【八数码】【A*】
- POJ1077 HDU1043 Eight 八数码第四境界 双向广搜 康托展开 逆康托
- POJ1077&HDU1043 Eight 八数码第八境界 IDA* hash 康托展开 奇偶剪枝
- POJ 1077 Eight(BFS八数码问题)
- hdu 1043 eight 八数码问题
- POJ 1077 Eight, 八数码问题
- Poj 1077 Eight 八数码问题 (搜索)
- NYOJ 22题 素数求和问题
- SQL字段类型
- .net MVC中如何使用iframe实现局部刷新
- C++中参数传递方式讨论
- Mahout源码K均值聚类算法分析(5)
- HDU1043 eight 八数码问题
- Eclipse中如何创建maven web工程
- android广告
- How can I launch Matlab 2012?
- 分享8年开发经验,浅谈程序员职业规划
- C++11的语法新特性
- VS2012快捷键
- xml作用 Input类型
- HDU4540+DP