# HDU - 1043 Eight(八数码+康拓展开式+BFS暴力打表)

Eight
Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
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:
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 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, 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
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

#include <iostream>
#include <cstring>
#include <queue>
#include <stack>
#include <map>
using namespace std;
char str[50];
int buf[10],go[4][2] = {0,1,0,-1,1,0,-1,0};
long fac[9];
int m,n;

struct node{
char dir;//记录方向
long father;//记录上一个节点
}que[370000];//用数组储存树形结构

struct node1{
int map[10];
long por;//代表当前字符串的的位置(位置右康拓展开式决定)
int n;//n是x在字符串中的位置。
};
int set_fac(int a)//计算阶乘
{
long ans = 1;
for (int i = 1;i <= a; i++){
ans *= i;
}
return ans;
}
long cantor(int *buf)//康拓展开
{
long ans = 0;
for (int i = 0;i < 9; i++){
int por = 0;
for (int j = i+1;j < 9; j++){
if (buf[i] > buf[j])
por++;
}
ans += por * fac[8-i];
}
return ans;
}

void bfs()
{
node1 p,q;
queue <node1> Q;
for (int i = 0; i < 9;i++){
p.map[i] = i+1;//初始化队列中第一个节点，其排列状态便是最正确的状态，再从这个状态去衍生出所有情况从而暴力打表
}
p.n = 8;
p.por = 0;
que[p.por].father = 0;
Q.push(p);
while (!Q.empty()){
q = Q.front();
Q.pop();
for (int i = 0;i < 4; i++){
p = q;
int tx = q.n/3+go[i][0],ty = q.n%3+go[i][1];//坐标分解
if (tx >= 0 && ty >= 0 && tx < 3 && ty < 3){
int tem;
p.n = tx*3 + ty;//坐标合并
tem = p.map[p.n];//交换
p.map[p.n] = p.map[q.n];
p.map[q.n] = tem;//交换
p.por = cantor(p.map);//计算康拓值
if (que[p.por].father == -1){
switch(i){//这里假如当i==0的时候，其实是向右，但是由于查表的时候是反正查的，所以这里记录的方向也要相反方便查表
case 0:que[p.por].dir = 'l';break;
case 1:que[p.por].dir = 'r';break;
case 2:que[p.por].dir = 'u';break;
case 3:que[p.por].dir = 'd';break;
}
que[p.por].father = q.por;//当前节点的父节点就是上一节点的康拓值
Q.push(p);
}
}
}
}
}
int main ()
{
for (int i = 0;i < 9; i++){
fac[i] = set_fac(i);
}
for (long i = 0;i < 370000; i++){
que[i].father = -1;
}
bfs();
while (gets(str) != NULL){
for (int i = 0,j = 0;str[i]; i++){//将字符串转化为int型。
if (str[i] == 'x'){
buf[j++] = 9;
}
else{
if (str[i] >= '0' && str[i] <= '8'){
buf[j++] = str[i] - '0';
}
}
}
long s = cantor(buf);
if (que[s].father == -1){//树中每一个节点的状态都是从正确状态变换而来，不在树内说明无法反向回到根节点达成目标。
printf ("unsolvable\n");
}
else{
while (s){
printf ("%c",que[s].dir);
s = que[s].father;
}
printf ("\n");
}
}
return 0;
}

• 本文已收录于以下专栏：

举报原因： 您举报文章：HDU - 1043 Eight(八数码+康拓展开式+BFS暴力打表) 色情 政治 抄袭 广告 招聘 骂人 其他 (最多只允许输入30个字)