原题目:https://leetcode-cn.com/problems/sliding-puzzle/
思路:
典型的BFS。
将二维的数组降维成字符串方便处理,记录0在每一个位置的可以变换的位置(数组neighbor)。
为了节省时间,我们可以用set记录已经遍历过的情况,防止死循环。
代码:
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& board) {
int m = 2, n = 3;
string start = "";
string target = "123450";//结束的情况
// 将 2x3 的数组转化成字符串
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
start.push_back(board[i][j] + '0');
}
}
// 记录可以交换的索引编号,比如如果0在位置0,那么可以与1,3交换
vector<vector<int>> neighbor = {
{ 1, 3 },
{ 0, 4, 2 },
{ 1, 5 },
{ 0, 4 },
{ 3, 1, 5 },
{ 4, 2 }
};
queue<string> q;
unordered_set<string> visited;//记录访问过的状态,防止再次访问
q.push(start);
visited.insert(start);
int step = 0;
while (!q.empty()) {
int sz = q.size();
for (int i = 0; i < sz; i++) {
string cur = q.front(); q.pop();
// 判断是否达到目标局面
if (target == cur) {
return step;
}
// 找到数字 0 的索引
int idx = 0;
for (; cur[idx] != '0'; idx++);
// 将数字 0 和相邻的数字交换位置
for (int adj : neighbor[idx]) {
string new_board = cur;
swap(new_board[adj], new_board[idx]);
// 防止走回头路
if (!visited.count(new_board)) {
q.push(new_board);
visited.insert(new_board);
}
}
}
step++;
}
return -1;
}
};