题面:https://www.luogu.org/problem/P1379
本题直接双向bfs,那么双向bfs就是把初始状态和终止状态都放进队列里,然后将二者设定为不同的方向,同时跑bfs,若目的状态和当前状态相同,目的状态无需再次入队,若目的状态和当前状态方向相反,那么直接输出答案,若目标状态没有入队过,那么把目标状态放进队中.
Code:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<ctime>
#include<map>
#include<queue>
using namespace std;
int n,g=123804765;
int a[4][4],fx,fy,nx,ny,dx[4]={1,-1,0,0},dy[4]={0,0,1,-1};
queue<int> q;
map<int,int> v,ans;
void bfs(){
if(n==g){
printf("0");
return;
}
q.push(n);
q.push(g);
ans[n]=0;
ans[g]=1;
v[g]=2;
v[n]=1;
while(!q.empty()){
long long now,cur=q.front();
q.pop();
now=cur;
for(int i=3;i>=1;i--){
for(int j=3;j>=1;j--){
a[i][j]=now%10;
now/=10;
if(a[i][j]==0){
fx=i;
fy=j;
}
}
}
for(int i=0;i<4;i++){
nx=fx+dx[i],ny=fy+dy[i];
if(nx<1||nx>3||ny<1||ny>3){
continue;
}
swap(a[fx][fy],a[nx][ny]);
now=0;
for(int p=1;p<=3;p++){
for(int j=1;j<=3;j++){
now=now*10+a[p][j];
}
}
if(v[now]==v[cur]){
swap(a[fx][fy],a[nx][ny]);
continue;
}
if(v[now]+v[cur]==3){
printf("%d",ans[cur]+ans[now]);
return;
}
ans[now]=ans[cur]+1;
v[now]=v[cur];
q.push(now);
swap(a[fx][fy],a[nx][ny]);
}
}
}
int main(){
scanf("%d",&n);
bfs();
return 0;
}