BFS AcWing 845 八数码
BFS AcWing 845 八数码
题目描述
在一个 x
恰好不重不漏地分布在这
例如:
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
现在,给你一个初始网格,请你求出得到正确排列至少需要进行多少次交换。
输入格式
输入占一行,将
例如,如果初始网格如下所示:
1 2 3 x 4 6 7 5 8
则输入为:1 2 3 x 4 6 7 5 8
输出格式
输出占一行,包含一个整数,表示最少交换次数。
如果不存在解决方案,则输出
输入样例:
2 3 4 1 5 x 7 6 8
输出样例
19
思路
BFS算法的经典板子题。
注意以下几点:
- 输入的一维字符串要进行一维转二维的操作才能利用方向数组。
- 二维运算后必须再转一维字符串加入队列。
- 注意边界条件。
- 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; }
分类:
搜索 剪枝
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~