leetcode#773. Sliding Puzzle
Problem Description
On a 2x3 board, there are 5 tiles represented by the integers 1 through 5, and an empty square represented by 0.
A move consists of choosing 0 and a 4-directionally adjacent number and swapping it.
The state of the board is solved if and only if the board is [[1,2,3],[4,5,0]].
Given a puzzle board, return the least number of moves required so that the state of the board is solved. If it is impossible for the state of the board to be solved, return -1.
Analyze
The problem is not so hard that you can easily think of BFS. And the matter is that how to deal with the moves and check if the board is explored.
There are several points that my code could be improved:
- we can use a map to record the next moves
- we can encode the board in form of string and use another map to record the moves
And my code is following:
class Solution {
public:
int slidingPuzzle(vector<vector<int>>& board) {
if (isFinal(board)) return 0;
visit(board, -1);
while (!q.empty()) {
vector<vector<int>>& cur = q.front();
int move = moves[cur[0][0] * 6 * 6 * 6 * 6 * 6 + cur[0][1] * 6 * 6 * 6 * 6 + cur[0][2] * 6 * 6 * 6 + cur[1][0] * 6 * 6 + cur[1][1] * 6 + cur[1][2]];
for (int i=0; i<2; i++) {
for (int j=0; j<3; j++) {
if (cur[i][j] == 0) {
int opt[5] = {1, 0, -1, 0, 1};
for (int k=0; k<4; k++) {
if (i+opt[k]>=0 && i+opt[k] < 2 && j+opt[k+1] >= 0 && j+opt[k+1] < 3) {
// construct the new board
vector<vector<int>> tmp(cur);
// swap the adjacent tiles
tmp[i+opt[k]][j+opt[k+1]] ^= tmp[i][j];
tmp[i][j] ^= tmp[i+opt[k]][j+opt[k+1]];
tmp[i+opt[k]][j+opt[k+1]] ^= tmp[i][j];
if (isFinal(tmp)) return move+1;
if (!isVisited(tmp)) visit(tmp, move);
}
}
break;
}
}
}
q.pop();
}
return -1;
}
private:
bool isFinal(vector<vector<int>>& board) {
return board[0][0] == 1 && board[0][1] == 2 && board[0][2] == 3 && board[1][0] == 4 && board[1][1] == 5 && board[1][2] == 0;
}
bool visited_boards[100000]; // record if the board is visited
int moves[100000]; // record the moves to the board
queue<vector<vector<int>>> q; // the adjacent boards
// check if a board is visited
bool isVisited(vector<vector<int>>& board) {
return visited_boards[board[0][0] * 6 * 6 * 6 * 6 * 6 + board[0][1] * 6 * 6 * 6 * 6 + board[0][2] * 6 * 6 * 6 + board[1][0] * 6 * 6 + board[1][1] * 6 + board[1][2]];
}
// visit the board
void visit(vector<vector<int>> board, int move) {
visited_boards[board[0][0] * 6 * 6 * 6 * 6 * 6 + board[0][1] * 6 * 6 * 6 * 6 + board[0][2] * 6 * 6 * 6 + board[1][0] * 6 * 6 + board[1][1] * 6 + board[1][2]] = true;
q.push(board);
moves[board[0][0] * 6 * 6 * 6 * 6 * 6 + board[0][1] * 6 * 6 * 6 * 6 + board[0][2] * 6 * 6 * 6 + board[1][0] * 6 * 6 + board[1][1] * 6 + board[1][2]] = move + 1;
}
};