链接:773. 滑动谜题
题解:https://blog.csdn.net/INGNIGHT/article/details/131350054
滑动拼图 II
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& board) {
// 异常判断
if (board.size() <= 0 || board[0].size() <= 0) {
return 0;
}
int m = board.size();
int n = board[0].size();
// 将矩阵归一化为字符串
std::string begin;
for (int i = 0; i < m; ++i) {
for (int j = 0; j < n; ++j) {
begin += (board[i][j] + '0');
}
}
// 终点
std::string end = "123450";
// bfs遍历队列
std::deque<std::string> que;
que.push_back(begin);
// 距离起点的距离
std::unordered_map<std::string, int> distance;
distance[begin] = 0;
// 一直遍历到队列为空
while (!que.empty()) {
auto f = que.front();
que.pop_front();
// 获得从当前0位置可以置换的四周位置
for (auto& neigh : get_neighbord(m, n, f)) {
// 如果当前位置遍历过
if (distance.find(neigh) != distance.end()) {
continue;
}
// 放入队列
que.push_back(neigh);
// 更新距离
distance[neigh] = distance[f] + 1;
}
}
// 判断是否到达最终点
return distance.find(end) == distance.end() ? -1 : distance[end];
}
private:
std::vector<std::string> get_neighbord(int m, int n, const std::string& node) {
std::vector<std::string> neighboards;
// 初始化空间
neighboards.reserve(4);
std::vector<std::vector<int>> direction{{0, -1}, {0, 1}, {1, 0}, {-1, 0}};
// 获得当前空块0的位置
int index = node.find('0');
// 转换为所在矩阵中位置
int row = index / n;
int col = index % n;
// 遍历4个方向,或者置换后的字符串
for (int i = 0; i < direction.size(); ++i) {
int next_row = row + direction[i][0];
int next_col = col + direction[i][1];
// 判断异常边界
if (next_row < 0 || next_col < 0
|| next_row >= m || next_col >= n) {
continue;
}
// 计算下一个位置点,置换字符串
int next_pos = next_row * n + next_col;
std::string bak = node;
swap(bak[index], bak[next_pos]);
// 追加邻居,置换后的字符串
neighboards.push_back(bak);
}
return neighboards;
}
};