1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 x
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->
思路:这个题hdu比poj的要紧一点,所以hdu能过的话poj一般就没问题。
用bfs去打表,一共只有9!(大概37w)个状态,不算多,记录从12345678_这个状态能够走到的所有的状态,并记录其父亲状态以及走的方向
然后我们每次输入序列只要一直找父亲,边输出路径,直到找到根结束即可。
方向就记反向的,方便我们找的时候直接输出。
记录一个序列,我们可以用hash,当然用普通hash是不行的,要用到康托展开hash,可以去看下我的前一篇博客或者百度百科,很好理解的东西。
不太会用A*...所以还没看懂A*的解法,真是菜啊=-=
代码:
#include
#include
#include
#include
#include
#include
using namespace std;
struct Node
{
char step;
int father;
} node[380005];
struct Node1
{
int a[10];
int n,id;
};
int f[10],num[10];
int dir[4][2]= {-1,0,1,0,0,1,0,-1};
void init()
{
f[0]=1;
for(int i=1; i<=8; i++)
f[i]=f[i-1]*i;
for(int i=1; i<380000; i++)
node[i].father=-1;
node[0].father=0;
}
int cantor(int *a)
{
int ans=0;
for(int i=1; i<=9; i++)
{
int k=0;
for(int j=i+1; j<=9; j++)
if(a[i]>a[j])
k++;
ans+=k*f[9-i];
}
return ans;
}
void bfs()
{
queueque;
Node1 q,next;
memcpy(q.a,num,sizeof(num));
q.n=9;
q.id=0;
que.push(q);
while(!que.empty())
{
Node1 now=que.front();
que.pop();
for(int i=0; i<4; i++)
{
int x= now.n%3==0?now.n/3+dir[i][0]:now.n/3+1+dir[i][0];
int y= now.n%3==0?dir[i][1]+3:now.n%3+dir[i][1];
if(x<1||x>3||y<1||y>3) continue;
next.n=(x-1)*3+y;
memcpy(next.a,now.a,sizeof(now.a));
swap(next.a[now.n],next.a[next.n]);
next.id=cantor(next.a);
if(node[next.id].father==-1)
{
node[next.id].father=now.id;
if(i==0) node[next.id].step='d';
else if(i==1) node[next.id].step='u';
else if(i==2) node[next.id].step='l';
else node[next.id].step='r';
que.push(next);
}
}
}
}
int main()
{
char op[100];
int ans[10];
init();
for(int i=1; i<=9; i++)
num[i]=i;
bfs();
while(gets(op)>0)
{
int t=0;
for(int i=0; i='0'&&op[i]<='9') ans[++t]=op[i]-'0';
}
int id=cantor(ans);
if(node[id].father==-1)
{
printf("unsolvable\n");
continue;
}
while(id)
{
printf("%c",node[id].step);
id=node[id].father;
}
printf("\n");
}
return 0;
}