P1379 八数码难题 未完结

传送门

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;
}
posted @ 2025-11-05 10:42  mark2025  阅读(8)  评论(0)    收藏  举报