初次见到这个题目,我是懵逼的。
本来去参考了kuangbin的代码,由于oj数据更新了,他写的两个代码一个mle,一个tle。后来参考的:http://blog.csdn.net/pmt123456/article/details/52906220,才发现了kuangbin代码mle的原因。mle的是逆向搜索打表的那个代码。
在逆向搜索的时候,如果每个节点都保存一个当前九宫格的状态的话,会导致mle,所以就不在每个节点都保存状态,而是用逆康拓展开还原出原来的状态。
#include <iostream>
#include <cstdio>
#include <queue>
#include <string>
#include <cstring>
using namespace std;
const int maxn = 362880+5;
int fac[9] = {1,1,2,6,24,120,720,5040,40320};
char path[maxn][42];
int vis[maxn];
int dxy[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
char dir[] = "durl";
struct node
{
node(int p, int s, int l):pos(p),status(s),len(l) {}
int pos;
int status;
int len;
};
int Cantor(int *s)
{
int i,j,num,temp;
num = 0;
for(i = 0; i < 9; ++i)
{
temp = 0;
for(j = i+1; j < 9; ++j)
if(s[j] < s[i]) ++temp;
num += fac[8-i]*temp;
}
return num;
}
void CantorReverse(int *s, int val)
{
int flag[10];
memset(flag,0,sizeof(flag));
for(int i = 0; i < 9; ++i)
{
int rk = val/fac[8-i];
for(int j = 0; j <= rk; ++j)
if(flag[j]) ++rk;
s[i] = rk;
flag[rk] = 1;
val = val%fac[8-i];
}
}
void bfs()
{
queue<node> que;
int s[] = {1,2,3,4,5,6,7,8,0};
node n(8,Cantor(s),0);
vis[n.status] = 1;
path[n.status][0] = '\0';
que.push(n);
while(!que.empty())
{
n = que.front();
que.pop();
int x = n.pos/3;
int y = n.pos%3;
for(int k = 0; k < 4; ++k)
{
int newx = x + dxy[k][0];
int newy = y + dxy[k][1];
if(newx < 0 || newy < 0 || newx > 2 || newy > 2) continue;
int newpos = newx*3 + newy;
CantorReverse(s,n.status);
swap(s[n.pos],s[newpos]);
int nstatus = Cantor(s);
if(!vis[nstatus])
{
vis[nstatus] = 1;
for(int i = 0; i < n.len; ++i)
path[nstatus][i] = path[n.status][i];
path[nstatus][n.len] = dir[k];
path[nstatus][n.len+1] = '\0';
que.push(node(newpos,nstatus,n.len+1));
}
swap(s[n.pos],s[newpos]);
}
}
}
int main()
{
memset(vis,0,sizeof(vis));
bfs();
char tmp;
int in[9];
while (scanf(" %c",&tmp) != EOF)
{
if (tmp == 'x')in[0] = 0;
else in[0] = tmp - '0';
for (int i = 1; i<9; ++i)
{
scanf(" %c",&tmp);
if (tmp == 'x')in[i] = 0;
else in[i] = tmp - '0';
}
int status = Cantor(in);
if (!vis[status]) printf("unsolvable\n");
else
{
int len = strlen(path[status]);
for (int i = len - 1; i >= 0; --i)printf("%c", path[status][i]);
printf("\n");
}
}
return 0;
}