Eight puzzle --HOJ 11918
1、题目类型:模拟、哈希表、BFS。
2、解题思路:(1)模拟Eigh Puzzle的变换方式,并记录在数组中 ;(2)由于变换的最终结果相同,所以采用反向的BFS遍历所有情况,并记录所有情况;(3)在查找情况过程中采用二进制哈希表形式,以便于查找;(4)根据题目每个输入的case对表中进行对应查找,直接输出答案。
3、注意事项:注意哈希表方式,否则TLE。
4、实现方法:(由于又借用模板,所以代码有点乱)
#include<iostream>
#include<string>
using namespace std;
const int r[] = {0,1,4,3,0,3,4,1,1,2,5,4,1,4,5,2,3,4,7,6,3,6,7,4,4,5,8,7,4,7,8,5};
int final[] = {69074,77576,135289,157120,205759,227590,285303,293805};
int p[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320};
int d[362880], q[362880];
int s[9];
int Encode(int* s)
{
int i,j,k,x = 0;
for(i=0;i<9;i++)
{
k = s[i];
for(j=0;j<i;j++)
if(s[j]<s[i])
k--;
x+=k*p[8-i];
}
return x;
}
void Decode(int* s, int x)
{
int i,j;
for(i=0;i<9;i++)
{
s[i]=x/p[8-i];
x%=p[8-i];
}
for(i=8;i>=0;i--)
for(j=8;j>i;j--)
if(s[j]>=s[i])
s[j]++;
}
void Init()
{
int i,x,y,front,rear,ss[9];
memset(d,-1,sizeof(d));
for(i=0;i<9;i++)
ss[i]=i;
q[0]=Encode(ss);
d[q[0]]=0;
front=0, rear=1;
while(front<rear)
{
x = q[front++];
Decode(s,x);
{
for(i=0;i<9;i++)
{
if(s[i]==8)
break;
}
if(i!=0 && i!=1 && i!=2)
{
s[i]=s[i-3];
s[i-3]=8;
y=Encode(s);
if(d[y]<0)
{
d[y] = d[x] + 1;
q[rear++] = y;
}
s[i-3]=s[i];
s[i]=9;
}
if(i!=2 && i!=5 && i!=8)
{
s[i]=s[i+1];
s[i+1]=8;
y=Encode(s);
if(d[y]<0)
{
d[y]=d[x]+1;
q[rear++]=y;
}
s[i+1]=s[i];
s[i]=8;
}
if(i!=6 && i!=7 && i!=8)
{
s[i]=s[i+3];
s[i+3]=8;
y=Encode(s);
if(d[y]<0)
{
d[y]=d[x]+1;
q[rear++]=y;
}
s[i+3]=s[i];
s[i]=8;
}
if(i!=0 && i!=3 && i!=6)
{
s[i]=s[i-1];
s[i-1]=8;
y=Encode(s);
if(d[y]<0)
{
d[y]=d[x]+1;
q[rear++]=y;
}
s[i-1]=s[i];
s[i]=8;
}
}
}
}
int main()
{
int i,T;
char ch;
Init();
cin>>T;
while(T--)
{
for(i=0;i<9;i++)
{
cin>>ch;
if(ch=='#')
s[i]=8;
else
s[i]=ch-'1';
}
if(d[Encode(s)]!=-1)
cout<<d[Encode(s)]<<endl;
else
cout<<"impossible"<<endl;
}
return 0;
}