BFS AcWing 845 八数码

BFS AcWing 845 八数码

题目描述

在一个 3×3 的网格中,188 个数字和一个 x 恰好不重不漏地分布在这 3×3 的网格中。

例如:

1 2 3
x 4 6
7 5 8

在游戏过程中,可以把 x 与其上、下、左、右四个方向之一的数字交换(如果存在)。

我们的目的是通过交换,使得网格变为如下排列(称为正确排列):

1 2 3
4 5 6
7 8 x

例如,示例中图形就可以通过让 x 先后与右、下、右三个方向的数字交换成功得到正确排列。

交换过程如下:

1 2 3 1 2 3 1 2 3 1 2 3
x 4 6 4 x 6 4 5 6 4 5 6
7 5 8 7 5 8 7 x 8 7 8 x

现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。

输入格式

输入占一行,将 3×3 的初始网格描绘出来。

例如,如果初始网格如下所示:

1 2 3
x 4 6
7 5 8

则输入为:1 2 3 x 4 6 7 5 8

输出格式

输出占一行,包含一个整数,表示最少交换次数。

如果不存在解决方案,则输出 1

输入样例:

2 3 4 1 5 x 7 6 8

输出样例

19

思路

BFS算法的经典板子题。

注意以下几点:

  1. 输入的一维字符串要进行一维转二维的操作才能利用方向数组。
  2. 二维运算后必须再转一维字符串加入队列。
  3. 注意边界条件。
  4. unordered_map进行去重,如果重复就剪枝。

代码

#include <iostream>
#include <queue>
#include <unordered_map>
using namespace std;
int bfs(string start)
{
// 存储各次字符情况的状态图,string类型
queue<string> q;
// 存储变换到相应状态图所需的最小步数
unordered_map<string, int> d;
// 初始化队列
q.push(start);
d[start] = 0;// 初始步数为0
string END = "12345678x";
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, -1, 0, 1};
// 队列
while (q.size()){
// 获取当前状态
string t = q.front();
q.pop();
int dist = d[t];// 在哈希表里查找状态图t的最小步数
if (t == END) return dist;// 如果已经成为最后要求的状态,则返回步数
// 状态转移
int k = t.find('x');// 找到x的位置
int x = k / 3, y = k % 3;// 一维转二维
for (int i = 0; i < 4; i++){
int a = x + dx[i], b = y + dy[i];// 在3*3方格中上下左右遍历
if (a >= 0 && a < 3 && b >= 0 && b < 3){
swap(t[k], t[a * 3 + b]);// 注意这里要把二维转一维
// 如果x和数交换后出现了新的状态图
if (!d.count(t)){// 即在d中找键值t为空
d[t] = dist + 1;// t的最小步数更新为dist+1
q.push(t);// 把t入队,保证队列中所有状态图不会相同
}
swap(t[k], t[a * 3 + b]);// 注意,新的图t如果入队过了,就必须把刚交换的状态图调整回来
}
}
}
return -1;
}
int main()
{
string start;
for (int i = 0; i < 9; i++){
char c;
cin >> c;
start += c;
}
cout << bfs(start) << endl;
return 0;
}
posted @   AKgrid  阅读(3)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~
点击右上角即可分享
微信分享提示