八数码是非常经典的搜索题,不过这道有点不一样:
There are multiple test cases.
操蛋的是数据量灰常灰常多!
出题人还写了句:Any violent algorithm may gain TLE. So a smart method is expected.
喵喵喵?
总之直接每个数据bfs是妥妥的TLE。
不过我们开动脑筋想一想,发现这道题可以打表。
打表???
没错,关键就在于终止状态是一样的。
所以我们只需要最终的状态开始BFS,遍历每一个状态,存下需要的步数(注意访问不到的状态),然后就可以愉快地打表了~
每次只需bfs一遍!
至于状态怎么存,自行搜索康托展开。
代码很久以前写的,改了很多遍,大概比较丑,酌情看吧。。。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#define M 1000000
#define P 23333
#define ed 46233
using namespace std;
struct node
{
int num[10],x,step;
}st,fm;
char s[10];
queue <node> q;
int ppow[15],ans,book[1000010],sth;
bool vis[1000010];
int re;
int haha(node t)
{
long long sum=0;
for (int i=1;i<=9;i++)
{
int tot=0;
for (int j=i+1;j<=9;j++)
{
if (t.num[i]>t.num[j]) tot++;
}
sum+=tot*ppow[9-i];
}
return (int)sum;
}
void rebfs()
{
q.push(fm); vis[haha(fm)]=true;
while (!q.empty())
{
node now=q.front(); q.pop();
/*if (now.step==2) {printf(" %d %d\n",now.x,haha(now));
for (int i=1;i<=9;i++)
{
printf("%d ",now.num[i]);
}
printf("\n");}*/
int hanow=haha(now);
if (!book[hanow]) book[hanow]=now.step;
if (hanow==sth)
{
ans=now.step;
book[haha(st)]=ans;
return;
}
if (now.x>3)
{
node nn=now;
nn.x=now.x-3;
nn.num[now.x]=now.num[nn.x];
nn.num[nn.x]=0;
nn.step=now.step+1;
int th=haha(nn);
if (!vis[th])
{
vis[th]=true;
q.push(nn);
}
}
if (now.x<7)
{
node nn=now;
nn.x=now.x+3;
nn.num[now.x]=now.num[nn.x];
nn.num[nn.x]=0;
nn.step=now.step+1;
int th=haha(nn);
if (!vis[th])
{
vis[th]=true;
q.push(nn);
}
}
if (now.x%3!=1)
{
node nn=now;
nn.x=now.x-1;
nn.num[now.x]=now.num[nn.x];
nn.num[nn.x]=0;
nn.step=now.step+1;
int th=haha(nn);
if (!vis[th])
{
vis[th]=true;
q.push(nn);
}
}
if (now.x%3!=0)
{
node nn=now;
nn.x=now.x+1;
nn.num[now.x]=now.num[nn.x];
nn.num[nn.x]=0;
nn.step=now.step+1;
int th=haha(nn);
if (!vis[th])
{
vis[th]=true;
q.push(nn);
}
}
}
}
void init()
{
while (!q.empty()) q.pop();
memset(vis,0,sizeof(vis));
ans=-1;
re=5;
}
int main()
{
ppow[0]=1;
for (int i=1;i<=10;i++)
{
ppow[i]=(ppow[i-1]*i)%M;
}
/*node t;
for (int i=1;i<=8;i++)
{
t.num[i]=i;
}
t.num[9]=0;
printf("%d",haha(t));*/
for (int i=1;i<=8;i++)
{
fm.num[i]=i;
}
fm.num[9]=0; fm.x=9;
for (int i=1;i<=6;i++)
{
st.num[i]=i;
}
st.num[7]=8; st.num[8]=7; fm.x=9;
sth=haha(st);
rebfs();
//printf("%d",ans);
while (scanf("%c",&s[1])!=-1)
{
init();
for (int i=2;i<=9;i++)
{
getchar();
scanf("%c",&s[i]);
}
getchar();
for (int i=1;i<=9;i++)
{
if (s[i]!='x') st.num[i]=s[i]-'0';
else st.num[i]=0,st.x=i;
}
sth=haha(st);
//bfs();
ans=book[sth];
if (ans==0)
{
if (sth!=ed) printf("unsolvable\n");
else printf("0\n");
}
else printf("%d\n",ans);
/*for (int i=0;i<=46233;i++)
{
printf("%d ",book[i]);
}*/
}
}