赞
踩
思路:
题意:如下九宫格玩具,问将九宫格恢复成如下状态所需的最小步数
状态怎么表示?
用一维数组来表示,如上图,就表示为 “12345678x”
如何处理状态?
① 枚举x的上下左右四个位置,交换x和该位置,然后将此状态加入队列中;
② 然后队列依次出队,出队时判断当前状态是不是最终状态"12345678x",再枚举x的上下左右四个位置,直至队列为空,则返回-1,表示不能达到最终状态。
一句话思路:
枚举x的上下左右四个位置,交换x和该位置,然后将此状态加入队列中,然后依次出队重复上述操作,在出队时判断判断当前状态是不是最终状态"12345678x"。
---------------------------------------------------解法---------------------------------------------------
#include <iostream> #include <algorithm> #include <unordered_map> #include <queue> using namespace std; int bfs(string state) { queue<string> q; // 队列 unordered_map<string, int> d; // 哈希表:存储每个状态所用的最短步数 q.push(state); d[state] = 0; int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1}; string end = "12345678x"; // 定义结束状态 while (q.size()) { auto t = q.front(); q.pop(); if (t == end) return d[t]; int distance = d[t]; // 状态转移 int k = t.find('x'); // 找x的位置,find函数会返回x的数组下标 int x = k / 3, y = k % 3; // 用x、y来对x进行二维状态表示 for (int i = 0; i < 4; i ++ ) // 考虑上下左右四个方向 { int a = x + dx[i], b = y + dy[i]; if (a >= 0 && a < 3 && b >= 0 && b < 3) { swap(t[a * 3 + b], t[k]); // a * 3 + b将二维坐标又拉伸为一维 if (!d.count(t)) // 如果当前状态未出现过,加入队列中,避免重复操作 { d[t] = distance + 1; // 步数在之前的基础上+1 q.push(t); // 将当前状态加入队列 } swap(t[a * 3 + b], t[k]); // 交换回来,继续考虑下一个方向(上下左右) } } } return -1; } int main() { char s[2]; string state; // 存初始状态 for (int i = 0; i < 9; i ++ ) { cin >> s; state += *s; // 对于string而言,运算符 + 代表字符串的连接操作 } cout << bfs(state) << endl; return 0; }
可能存在的问题(所有问题的位置都在上述代码中标注了出来)
bfs的例题,理解思想并实现代码。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。