map+BFS
点击查看代码
#include<bits/stdc++.h>
using namespace std;
using LL=long long; // 使用long long类型存储状态
LL n; // 存储初始状态
// 方向数组:下、右、左、上(对应空格移动的四个方向)
LL fx[4]={1,0,0,-1};
LL fy[4]={0,1,-1,0};
int main()
{
cin>>n; // 输入初始状态,如283104765
// 使用BFS队列存储待处理的状态
queue<LL> q;
q.push(n); // 将初始状态加入队列
// 使用map记录每个状态对应的步数,同时起到visited集合的作用
map<LL,LL> mp;
mp[n]=0; // 初始状态的步数为0
// BFS主循环
while(!q.empty())
{
LL u,tx,ty;
LL kx=0,ky=0; // 存储空格0的x,y坐标
LL a[3][3]; // 3x3矩阵存储当前状态
LL ts; // 临时存储新生成的状态
u=q.front(); // 取出队首状态
q.pop();
LL tag=u; // 备份当前状态值
// 如果到达目标状态,退出循环
if(u==123804765) break;
// 将数字状态转换为3x3矩阵
// 从右下角到左上角填充矩阵(因为状态数字是从右往左读的)
for(int i=2;i>=0;i--)
{
for(int j=2;j>=0;j--)
{
a[i][j]=tag%10; // 取最后一位数字
tag/=10; // 去掉最后一位
if(!a[i][j]){ // 如果当前格子是空格0
kx=i; // 记录空格的x坐标
ky=j; // 记录空格的y坐标
}
}
}
// 尝试四个方向的移动
for(int i=0;i<4;i++)
{
// 计算空格移动后的新位置
tx=kx+fx[i];
ty=ky+fy[i];
ts=0; // 重置新状态值
// 检查新位置是否在棋盘范围内
if(tx>2||tx<0||ty>2||ty<0) continue;
// 交换空格和相邻格子(模拟移动)
swap(a[tx][ty],a[kx][ky]);
// 将3x3矩阵转换回数字状态
for(int p=0;p<=2;p++)
{
for(int j=0;j<=2;j++)
{
ts=ts*10+a[p][j]; // 逐位构建状态数字
}
}
// 如果新状态没有被访问过
if(!mp.count(ts))
{
mp[ts]=mp[u]+1; // 记录新状态的步数(当前状态步数+1)
q.push(ts); // 将新状态加入队列
}
// 恢复矩阵状态,为下一个方向的尝试做准备
swap(a[tx][ty],a[kx][ky]);
}
}
// 输出从初始状态到目标状态的最少步数
cout<<mp[123804765];
return 0;
}