题目链接:https://www.acwing.com/problem/content/847/
解题思路:先用str保存需要到的状态,用数组保存初始状态,将初始状态用string型入队列,拿出队头,转成二维数组方便上下左右移动,移完之后转成string入队列,每次拿出队头都与str(需要到的转态)判断,相等就直接输出,结束程序,如果通过队列为空退出的说明转不到需要的转态,输出-1.
代码如下:
#include <bits/stdc++.h>
using namespace std;
int fx[4][4]={{1,0},{0,1},{-1,0},{0,-1}};
unordered_map<string,int >m;//去掉map的排序功能,加快运行速度
int x,y;
char a[5][5];
queue<string>q;
void fun(string p){
a[1][1]=p[0];
a[1][2]=p[1];
a[1][3]=p[2];
a[2][1]=p[3];//转成数组,懒得写循环了
a[2][2]=p[4];
a[2][3]=p[5];
a[3][1]=p[6];
a[3][2]=p[7];
a[3][3]=p[8];
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
if(a[i][j]=='x'){
x=i;
y=j;//记下x的坐标,只能移他的上下左右移
break;
}
}
}
}
int main()
{
string str="12345678x";
string str1;
for(int i=1;i<=3;i++){
for(int j=1;j<=3;j++){
cin>>a[i][j];
str1+=a[i][j];
}
}
q.push(str1);
m[str1]=0;//初始状态需要的步数
while(q.size()){
string st=q.front();//拿出队头
//cout<<st<<" ";
if(st==str){//相等了结束程序
cout<<m[st];
return 0;
}
q.pop();
fun(st);
for(int i=0;i<4;i++){
int j,k;
j=x+fx[i][0];
k=y+fx[i][1];
if(j<1||k<1||j>3||k>3) continue;
a[x][y]=a[j][k];//上下左右移
a[j][k]='x';
string bh="";
for(int w=1;w<=3;w++){
for(int r=1;r<=3;r++){
bh+=a[w][r];//把移完的转成字符串
}
}
//cout<<bh<<endl;;
if(m[bh]==0){//移完的字符串已经出现过了,就不需要入队列
q.push(bh);
}
a[j][k]=a[x][y];
a[x][y]='x';
m[bh]=m[st]+1;//步数等于它上一个状态的步数加一
}
}
cout<<-1;//转不到要的状态,输出-1
return 0;
}