#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=370000;
int fac[15] = {1,1,2,6,24,120,720,5040,40320,362880};//记录1-10的阶乘
bool vis[MAXN];
int step[MAXN];
int q1[MAXN],q2[MAXN],front,rear;//q1放数字值,q2放康托压缩后的值
int Cantor(int a[],int n) {
int s = 1;
int sum = 1; //sum从1开始
for(int i = 0; i < n; i++) {
s = 0;
for(int j = i+1; j<n; j++) {
if(a[j] < a[i])
s++;
}
sum +=s * fac[n-1-i];
}
return sum;
}
//把数组a中的数转化为一个9位数
int getnum(int a[]) {
int ans=0;
for(int i=0; i<9; i++) {
ans*=10;
ans+=a[i];
}
return ans;
}
int main() {
memset(step,-1,sizeof(step));
int a[9]= {1,2,3,8,0,4,7,6,5};
int end=getnum(a);
int endCantor=Cantor(a,9);
for(int i=0; i<9; i++)
cin>>a[i];
int begin=getnum(a);
int beginCantor=Cantor(a,9);
vis[beginCantor]=1;//此状态已访问
step[beginCantor]=0;
q1[rear]=begin;
q2[rear]=beginCantor;
rear++;
//cout<<begin<<":"<<end<<endl;
if(begin==end) {
cout<<0<<endl;
return 0;
}
while(front<rear) {
int temp=q1[front];
int tempCantor=q2[front];
front++;
//找temp中0的位置find
int find;
//cout<<"队头:"<<temp<<endl;
int t=temp;
for(int i=8; i>=0; i--) {
a[i]=t%10;
t/=10;
if(a[i]==0)
find=i;
}
//cout<<"0的位置:"<<find<<endl;
//把上下左右交换后的状态加入队列
//上
if(find>=3) {
swap(a[find],a[find-3]);
t=Cantor(a,9);
//cout<<temp<<"交换上侧:"<<getnum(a)<<endl;
if(!vis[t]) {
vis[t]=1;
step[t]=step[tempCantor]+1;
q2[rear]=t;
t=getnum(a);
if(t==end) {
break;
}
q1[rear]=t;
rear++;
//cout<<t<<"入队"<<endl;
}
swap(a[find],a[find-3]);
}
//右
if((find+1)%3!=0) {
swap(a[find],a[find+1]);
t=Cantor(a,9);
//cout<<temp<<"交换右侧:"<<getnum(a)<<endl;
if(!vis[t]) {
vis[t]=1;
step[t]=step[tempCantor]+1;
q2[rear]=t;
t=getnum(a);
if(t==end) {
break;
}
q1[rear]=t;
rear++;
//cout<<t<<"入队"<<endl;
}
swap(a[find],a[find+1]);
}
//下
if(find<=5) {
swap(a[find],a[find+3]);
t=Cantor(a,9);
//cout<<temp<<"交换下侧:"<<getnum(a)<<endl;
if(!vis[t]) {
vis[t]=1;
step[t]=step[tempCantor]+1;
q2[rear]=t;
t=getnum(a);
if(t==end) {
break;
}
q1[rear]=t;
rear++;
//cout<<t<<"入队"<<endl;
}
swap(a[find],a[find+3]);
}
//左
if(find%3!=0) {
swap(a[find],a[find-1]);
t=Cantor(a,9);
//cout<<temp<<"交换左侧:"<<getnum(a)<<endl;
if(!vis[t]) {
vis[t]=1;
step[t]=step[tempCantor]+1;
q2[rear]=t;
t=getnum(a);
if(t==end) {
break;
}
q1[rear]=t;
rear++;
//cout<<t<<"入队"<<endl;
}
swap(a[find],a[find-1]);
}
}
if(step[endCantor]==-1)
cout<<-1;
else
cout<<step[endCantor];
return 0;
}
八数码问题
最新推荐文章于 2025-04-25 21:12:48 发布