题意
就是问你怎么走可以最后走成:1 2 3 4 5 6 8 x 的状态
思路
由于起点和终点已经知道所以可以用双向bfs,我们考虑bfs的树状图形
我们可以看到阴影部分的地方就是无用的地方,我们双向搜索的话,肯定能找到相同的一层!(注意这里是一层),所以我们双向bfs的策略就是:你走一层,我走一层,这样相会的时候就是路径最短的时候,因为层数相当于步数!至于路劲的问题就很简单了,用pre[i]记录i是由pre[i]走过来的,走的方式是path[i],注意从终点走过来的方向是相反的。还有当你输出的方案跟原答案不一样的时候没关系,因为我现在才知道这个问题的最优解不是唯一的,可以有多种走法,但是走的步数必须是最短的!!!例如我的输出就是ullddrurdllurrdlurd
#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
const int MAXN=400000;
struct node{
int location,index;
int str[10];
}num[MAXN];
int f[] = {1, 1, 2, 6, 24, 120, 720, 5040, 40320, 362880};
int mx[4]={1,0,-1,0};
int my[4]={0,1,0,-1};
char dir[2][4]={{'d','r','u','l'},{'u','l','d','r'}};
int pre1[MAXN],pre2[MAXN];
int vis1[MAXN],vis2[MAXN];
int path1[MAXN],path2[MAXN];
node st,et;
int cantor(int *a)
{
int t=8,sum=0;
for(int i=0;i<9;i++)
{
int s=0;
for(int j=i+1;j<9;j++) if(a[i]>a[j]) s++;
sum+=s*f[t-i];
}
return sum+1;
}
queue <node> q1,q2;
int d2;
int fg=0;
void bfs()
{
memset(vis1,0,sizeof(vis1));
memset(vis2,0,sizeof(vis2));
vis1[st.index]=1;
vis2[et.index]=2;
q1.push(st);
q2.push(et);
pre1[st.index]=-1;
pre2[et.index]=-1;
while(!q1.empty()||!q2.empty())
{
int s1=q1.size();
while(s1--)
{
node t=q1.front();q1.pop();
if(vis2[t.index]==2){
fg=1;
d2=t.index;
return;
}
for(int i=0;i<4;i++)
{
int xx=t.location/3+mx[i];int yy=t.location%3+my[i];
if(xx>=0&&xx<3&&yy>=0&&yy<3)
{
node t2;
for(int i=0;i<9;i++) t2.str[i]=t.str[i];
int tt=xx*3+yy;
swap(t2.str[tt],t2.str[t.location]);
t2.location=tt;
t2.index=cantor(t2.str);
if(!vis1[t2.index])
{
q1.push(t2);
vis1[t2.index]=1;
path1[t2.index]=i;
pre1[t2.index]=t.index;
}
}
}
}
int s2=q2.size();
while(s2--)
{
node t=q2.front();q2.pop();
if(vis1[t.index]==1)
{
fg=1;
d2=t.index;
return;
}
for(int i=0;i<4;i++)
{
int xx=t.location/3+mx[i];int yy=t.location%3+my[i];
if(xx>=0&&xx<3&&yy>=0&&yy<3)
{
node t2;
for(int i=0;i<9;i++) t2.str[i]=t.str[i];
int tt=xx*3+yy;
swap(t2.str[tt],t2.str[t.location]);
t2.index=cantor(t2.str);
t2.location=tt;
if(!vis2[t2.index])
{
q2.push(t2);
vis2[t2.index]=2;
path2[t2.index]=i;
pre2[t2.index]=t.index;
}
}
}
}
}
}
int dd1[MAXN],dd2[MAXN];
int main()
{
for(int i=0;i<9;i++)
{
et.str[i]=i+1;
char t;cin>>t;
if(t=='x') st.str[i]=9,st.location=i;
else st.str[i]=t-'0';
}
et.location=8;
et.index=cantor(et.str);
st.index=cantor(st.str);
bfs();
if(!fg) printf("unsolvable\n");
else
{
int d1=d2;
int cont=0;
while(pre1[d1]!=-1)
{
dd1[cont++]=path1[d1];
d1=pre1[d1];
}
for(int i=cont-1;i>=0;i--) printf("%c",dir[0][dd1[i]]);
cont=0;
d1=d2;
while(pre2[d1]!=-1)
{
dd2[cont++]=path2[d1];
d1=pre2[d1];
}
for(int i=0;i<cont;i++) printf("%c",dir[1][dd2[i]]);
}
return 0;
}