原题~传送门
1.bfs+康托展开+打表+路径记录
2.反向思维
#include<bits/stdc++.h>
using namespace std;
const int maxs = 4e5;
//const int AIM = 46234 ;//12456780对应的康托展开的hash值
bool vis[maxs];
int op1[4][2]={{-1,0},{1,0},{0,-1},{0,1}};
char op2[5]="durl"; //因为bfs是从最终结果往回搜索,所以标记与op1对应的刚好相反
char path[maxs][40];
typedef struct
{
int s[10];
int x; //节点x所在s中的下标
int fa; //节点的父节点下标
int status; //节点康托展开对应的hash值
char op; //记录节点移动方向
}node;
node n[maxs];
int fac[10]={1,1,2,6,24,120,720,5040,40320,362880}; //康托展开对应的hash值
//n a的位数 ,字符表示的数a
int kangtuo(int n,int a[]) //返回数a康托展开对应的hash值
{
int sum =0;
int t=0;
for(int i=0;i<n;i++)
{
t = 0;
for(int j=i+1;j<n;j++)
{
if(a[i]>a[j])
{
t++;
}
}
sum += t*fac[n-i-1];
}
return sum + 1;
}
void count_path(node a)
{
int ans = a.status;
path[ans][0] = a.op;
int tp = a.fa;
int cnt = 1;
while(tp!=0)
{
path[ans][cnt++] = n[tp].op;
tp = n[tp].fa;
}
}
void bfs()
{
memset(vis,0,sizeof(vis));
n[0].fa =0;
n[0].s[8]=0; //0记为x所在点
for(int i=0;i<8;i++) //从最终结果出发
n[0].s[i] = i+1;
n[0].x = 8;
n[0].status = kangtuo(9,n[0].s);
vis[n[0].status] = true;
node next;
int head=0,tail=0;
// cout<<"!\n";
while(head<=tail)
{
int x,y;
x = n[head].x/3;
y = n[head].x%3;
for(int i=0;i<4;i++)
{
int dx = x + op1[i][0];
int dy = y + op1[i][1];
if(dx<0||dx>2||dy<0||dy>2) continue;
next = n[head];
next.x=dx*3 +dy;
next.s[n[head].x] = next.s[next.x]; //将原节点和next节点的0位置调整
next.s[next.x] = 0;
next.op = op2[i];
next.fa = head;
next.status = kangtuo(9,next.s);
if(!vis[next.status])
{
//cout<<"!"<<next.status<<'\n';
vis[next.status] = true;
n[++tail] = next;
count_path(next);
}
}
head++;
}
}
int main()
{
bfs();
char ch;
int s[10];
while(~scanf(" %c",&ch))
{
if(ch!='x') s[0] = ch-'0';
else s[0] = 0;
for(int i=1;i<9;i++)
{
scanf(" %c",&ch);
if(ch!='x') s[i] = ch-'0';
else s[i] = 0;
}
int st = kangtuo(9,s);
if(vis[st])
{
printf("%s\n",path[st]);
}
else printf("unsolvable\n");
}
return 0;
}