经典八码难题,又搞了我一晚上,所幸最后AC了,不过试着在POJ提交了下,TLE了。。HDU上也可以过,不知为毛。这题我最开始天真地直接单向BFS裸搜了,毫无疑问TLE,网上搜了搜,发现大牛竟然用A*做的。。完全不懂,还有一种是双向BFS,我改了下还是TLE,可能算法不对。最后经过长期思考,直接把12345678x这种最终状态反向BFS出所有有解的状态,即预处理了,存到map里面,加上状态的父节点和路径,这样的话根据输入可直接判出是否有解,然后打印路径,可能可以优化的地方是状态可以用hash表存,不知道时间上有没有提升,先不管了。。晚上搞的够恶心了
#include<cstdio>
#include<deque>
#include<map>
using namespace std;
namespace
{
int c[3][3];
int dir[4][2] = { { 0, 1 }, { 0, -1 }, { -1, 0 }, { 1, 0 } };
char ch[4] = { 'l', 'r', 'd', 'u' };
map<int, pair<int, char> > P;
pair<int, int> fill(int num)
{
pair<int, int> res;
for (int i = 2; i >= 0; i--)
for (int j = 2; j >= 0; j--)
{
c[i][j] = num % 10;
num /= 10;
if (c[i][j] == 9)
{
res.first = i;
res.second = j;
}
}
return res;
}
int number()
{
int res = 0;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 3; j++)
res = res * 10 + c[i][j];
return res;
}
void swap(int i1, int j1, int i2, int j2)
{
int temp = c[i1][j1];
c[i1][j1] = c[i2][j2];
c[i2][j2] = temp;
}
void print_path(int res)
{
while (res != 123456789)
{
putchar(P[res].second);
res = P[res].first;
}
putchar('\n');
}
void bfs()
{
deque<int> Q;
Q.push_back(123456789);
P.clear();
P[123456789] = make_pair(0, 0);
while (!Q.empty())
{
int now = Q.front();
Q.pop_front();
pair<int, int> p = fill(now);
for (int k = 0; k < 4; k++)
{
int i = p.first + dir[k][0];
int j = p.second + dir[k][1];
if (i >= 0 && i < 3 && j >= 0 && j < 3)
{
swap(p.first, p.second, i, j);
int n = number();
if (P.find(n) == P.end())
{
P[n] = make_pair(now, ch[k]);
Q.push_back(n);
}
swap(p.first, p.second, i, j);
}
}
}
}
}
int main()
{
char s[30];
bfs();
while (gets(s) != NULL)
{
int res = 0;
for (int i = 0; s[i] != '\0'; i++)
if (s[i] != ' ')
res = res * 10 + (s[i] == 'x' ? 9 : (s[i] - '0'));
if (P.find(res) != P.end())
print_path(res);
else
puts("unsolvable");
}
return 0;
}