题目链接:http://poj.org/problem?id=1077
题目大意:经典八数码问题, 给出初始状态, 求到终止状态的路径.
分析:A星,优先队列,Hash函数,路径记录.
/*A星,优先队列,Hash函数,路径*/
#include<iostream>
#include<map>
#include<string>
#include<queue>
#include<cstdio>
#include<cstring>
#include<cstdlib>
using namespace std;
#define maxn 362886
#define PRIME 362885
#define whatever 10
int tmp[10];
char goal[10] = { "123456780" };
//int rule[10][4] = { { 0, 0, 0, 0 }, { 1, 1, 0, 0 }, { 2, 2, 2, 0 }, { 0, 3, 3, 0 }, { 4, 4, 0, 4 }, { 5, 5, 5, 5 }, { 0, 6, 6, 6 }, { 7, 0, 0, 7 }, { 8, 0, 8, 8 }, { 0, 0, 9, 9 } };
int dx[4] = { 0, -1, 0, 1 }, dy[4] = { -1, 0, 1, 0 };
struct NODE
{
int map[3][3];
int x0, y0;
int sta;
int hash;
int f, g, h;
bool operator < (const NODE &a) const
{
if (a.f != f)
return a.f < f;
else
return a.g < g;
}
}t, u;
int mark[maxn];
struct
{
int num;
int dir;
}PRE[maxn];
int flag;
int PreJudge(int a[])
{
int sum = 0;
for (int i = 0; i < 8; i++)
for (int j = i + 1; j < 9; j++)
if (a[j] && a[i] && a[i] > a[j])
sum++;
return sum % 2 == 0 ? true : false;
}
int map_to_int()
{
int res = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
res = res * 10 + t.map[i][j];
return res;
}
int HASH(int sta)
{
int p = sta%PRIME;
while (mark[p] != 0 && mark[p] != sta)
p = (p + 1) % PRIME;
return p;
}
int get_h()
{
char s[35];
sprintf(s, "%d", t.sta);
int cnt = 0;
for (int i = 0; i < 9; i++)
if (s[i] != '0'&&s[i] != goal[i])
cnt++;
return cnt;
}
void A_star()
{
priority_queue<struct NODE> Q;
t.sta = map_to_int(); t.hash = HASH(t.sta); t.g = 0; t.h = get_h(); t.f = t.g + t.h;
PRE[t.hash].num = -1; PRE[t.hash].dir = -1;
Q.push(t);
if (t.sta == 123456780)
{
flag = 1;
return;
}
mark[t.hash] = t.sta;
while (!Q.empty())
{
u = Q.top(); Q.pop();
for (int dir = 0; dir < 4; dir++)
{
memcpy(t.map, u.map, sizeof(u.map));
//t = u;
int x = u.x0 + dx[dir], y = u.y0 + dy[dir];
if (0 <= x&&x < 3 && 0 <= y&&y < 3)
{
t.map[u.x0][u.y0] = u.map[x][y]; t.map[x][y] = 0;
t.sta = map_to_int(); t.hash = HASH(t.sta);
if (mark[t.hash] == 0)
{
t.g = u.g + 1; t.h = get_h(); t.f = t.g + t.h; t.x0 = x; t.y0 = y;
PRE[t.hash].num = u.hash;
PRE[t.hash].dir = dir;
Q.push(t);
if (t.sta == 123456780)
{
flag = 1;
return;
}
mark[t.hash] = t.sta;
}
}
}
}
}
int main()
{
freopen("f:\\input.txt", "r", stdin);
int i, j, k;
char str[30];
gets(str);
int len = strlen(str);
int top = 0;
j = k = 0;
for (i = 0; i < len; i++)
{
if (k == 3)
{
j++;
k = 0;
}
if ('1' <= str[i] && str[i] <= '8')
t.map[j][k++] = tmp[top++] = str[i] - '0';
else if (str[i] == 'x')
{
t.x0 = j;
t.y0 = k;
t.map[j][k++] = tmp[top++] = 0;
}
}
if (PreJudge(tmp) == false)
printf("unsolvable\n");
else
{
flag = 0;
memset(mark, 0, sizeof(mark));
A_star();
if (flag)
{
int ans[1000];
int top1 = 0;
int p = t.hash;
while (PRE[p].dir != -1)
{
ans[top1++] = PRE[p].dir;
p = PRE[p].num;
}
char str[5] = { "lurd" };
for (top1--; top1 >= 0; top1--)
printf("%c", str[ans[top1]]);
printf("\n");
}
else
printf("unsolvable\n");
}
return 0;
}