题意:给定一个现有的九宫格布局,请输出将它移动至初始状态的移动方法的步骤。
思路:自己没什么思路。学了康拓展开,看了别人的博客才理解了,暂且先放着别人的代码,,等自己实力足够了再自己写试试
//HDU1043-经典BFS-八数码
//多组数据-需要计算全部路径后直接输出(POJ1077数据较弱)
//反向搜索+打表(离线)
//Time:109Ms Memory:25412K
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
using namespace std;
#define MAX 400000
#define AIM 46234 //123456780对应的康托Hash值
bool v[MAX];
char path[MAX][40]; //总路径
int len; //路径长
/*udlr*/
char *dir = "durl"; //反向搜索
int mov[4][2] = { { -1, 0 }, { 1, 0 }, { 0, -1 }, { 0, 1 } };
//八数码状态结构体
struct Node{
int s[9];
int loc; //空位
int status; //Hash值-排列值
int fa; //记录父状态
char d; //到此状态的移动方向
}n[MAX];
int fac[10] = { 1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880 };
//康托逆展开-返回Hash值
int Inverse_cantor(int s[9])
{
int sum = 0;
for (int i = 0; i < 9; i++)
{
int num = 0; //逆序数计数器
for (int j = i + 1; j < 9; j++)
if (s[j] < s[i])
num++;
sum += num*fac[9 - i - 1];
}
return sum + 1;
}
/*反向记录路径*/
void count_path(Node end)
{
int status = end.status;
int f = end.fa;
len = 0;
path[status][len++] = end.d;
while (f)
{
path[status][len++] = n[f].d;//方向记录
f = n[f].fa; //查找父结点
}
}
void BFS()
{
memset(v, 0, sizeof(v));
Node next; //下一临时状态
int head = 0, tail = 0;
/*目标状态*/
for (int i = 0; i < 8; i++)
n[0].s[i] = i + 1;
n[0].s[8] = 0;
n[0].loc = 8;
n[0].status = AIM;
v[AIM] = true;
while (head <= tail) //模拟队列
{
//计算二维坐标
int x = n[head].loc / 3;
int y = n[head].loc % 3;
for (int i = 0; i < 4; i++) //遍历四方向
{
int tx = x + mov[i][0];
int ty = y + mov[i][1];
if (tx < 0 || tx>2 || ty < 0 || ty>2)continue;
//新状态更新
next = n[head];
next.loc = tx * 3 + ty; //计算新空位
next.s[n[head].loc] = next.s[next.loc]; //原空位替换
next.s[next.loc] = 0; //新空位
next.fa = head;
next.d = dir[i];
next.status = Inverse_cantor(next.s);
//判重并入队
if (!v[next.status])
{
v[next.status] = true;
count_path(next);
n[++tail] = next;
}
}
head++;
}
}
int main()
{
/* BFS-打表 */
BFS();
/*input*/
char ch[3];
Node cur;
while (scanf("%s", ch) != EOF)
{
if (!strcmp(ch, "x"))
cur.s[0] = 0, cur.loc = 0;
else cur.s[0] = ch[0] - '0';
for (int i = 1; i < 9; i++)
{
scanf("%s", ch);
if (!strcmp(ch, "x"))
cur.s[i] = 0, cur.loc = i;
else cur.s[i] = ch[0] - '0';
}
cur.status = Inverse_cantor(cur.s);
/*output*/
if (v[cur.status])
printf("%s\n", path[cur.status]);
else
printf("unsolvable\n");
}
return 0;
}