题面
题意
3*3的方格中有一个x,可以将x与它相邻的方块交换,使最终结果为
1 2 3
4 5 6
7 8 x
方法
用康拓展开式的方法,状压(也可以采用哈希表),然后通过不断的转换实现用1~362880(9!)来记录3*3中数字的状态
记录时,用9来代替x
再进行宽搜(从最终状态开始),用一个数组来记录达到各个状态之前的状态,并用另一个数组记录这次的移动
注意,因为是从最后的状态开始,所以方向与答案相反
代码
#include<bits/stdc++.h>
#define N 400000
using namespace std;
struct str
{
int zt,last;
};
queue<str>q;
int vis[N],a[4][4],aa=0,jc[10]={1,1,2,6,24,120,720,5040,40320,362880},ans[N];
char ch,ea[N];
bool P[10],da[N];
int kt1(string u)//将数字方格转化为康拓展开式
{
int cnt,sum=1,i,j;
for(i=0;i<9;i++)
{
cnt=0;
for(j=i+1;j<9;j++)
{
if(u[i]>u[j]) cnt++;
}
sum+=(cnt*jc[8-i]);
}
return sum;
}
string kt2(int u)//将康拓展开式转化为数字方格
{
int i,j,k,t;
char an[10];
u--;
for(i=1;i<=9;i++) P[i]=0;
for(i=0;i<=8;i++)
{
k=1;
while(u>=jc[8-i]*k) k++;
u-=(k-1)*jc[8-i];
t=1;
k--;
while(P[t]) t++;
while(k)
{
while(P[t]) t++;
t++;
k--;
}
while(P[t]) t++;
P[t]=1;
an[i]=t+48;
}
an[9]=0;
return an;
}
int main()
{
int i,j,x,y,t;
string k;
str tmp,tmp2;
tmp.zt=1;
tmp.last=-1;
vis[1]=1;
ans[1]=-1;
da[1]=1;
q.push(tmp);
while(!q.empty())
{
tmp=q.front();
q.pop();
k=kt2(tmp.zt);
da[tmp.zt]=1;
for(i=0;i<9;i++)
{
a[i/3+1][i%3+1]=k[i]-48;
if(k[i]=='9')
{
x=i/3+1;
y=i%3+1;
}
}
//up
if(x!=1)
{
k="";
swap(a[x][y],a[x-1][y]);
for(i=1;i<=3;i++)
{
for(j=1;j<=3;j++)
{
k+=a[i][j]+48;
}
}
if(!vis[kt1(k)])
{
vis[kt1(k)]=1;
tmp2.last=tmp.zt;
tmp2.zt=kt1(k);
q.push(tmp2);
ans[tmp2.zt]=tmp.zt;
ea[tmp2.zt]='d';
}
swap(a[x][y],a[x-1][y]);
}
//down
if(x!=3)
{
k="";
swap(a[x][y],a[x+1][y]);
for(i=1;i<=3;i++)
{
for(j=1;j<=3;j++)
{
k+=a[i][j]+48;
}
}
if(!vis[kt1(k)])
{
vis[kt1(k)]=1;
tmp2.last=tmp.zt;
tmp2.zt=kt1(k);
q.push(tmp2);
ans[tmp2.zt]=tmp.zt;
ea[tmp2.zt]='u';
}
swap(a[x][y],a[x+1][y]);
}
//left
if(y!=1)
{
k="";
swap(a[x][y],a[x][y-1]);
for(i=1;i<=3;i++)
{
for(j=1;j<=3;j++)
{
k+=a[i][j]+48;
}
}
if(!vis[kt1(k)])
{
vis[kt1(k)]=1;
tmp2.last=tmp.zt;
tmp2.zt=kt1(k);
q.push(tmp2);
ans[tmp2.zt]=tmp.zt;
ea[tmp2.zt]='r';
}
swap(a[x][y],a[x][y-1]);
}
//right
if(y!=3)
{
k="";
swap(a[x][y],a[x][y+1]);
for(i=1;i<=3;i++)
{
for(j=1;j<=3;j++)
{
k+=a[i][j]+48;
}
}
if(!vis[kt1(k)])
{
vis[kt1(k)]=1;
tmp2.last=tmp.zt;
tmp2.zt=kt1(k);
q.push(tmp2);
ans[tmp2.zt]=tmp.zt;
ea[tmp2.zt]='l';
}
swap(a[x][y],a[x][y+1]);
}
}
while(~scanf("%c",&ch))
{
k="";
if(ch=='x') ch='9';
i=1;
if(ch>='0'&&ch<='9')
k+=ch,i++;
for(;i<=9;i++)
{
scanf("%c",&ch);
if(ch=='x') ch='9';
if(ch<'0'||ch>'9')//若读到空格,跳过
{
i--;
continue;
}
k+=ch;
}
t=kt1(k);
if(!da[t])
{
printf("unsolvable\n");
continue;
}
while(t!=-1)
{
printf("%c",ea[t]);
t=ans[t];
}
printf("\n");
ch=getchar();
}
}