1.关键点:利用编码函数,将矩阵变为整数,作为存储的状态。再利用解码函数,将状态变为矩阵,进行BFS 新状态的遍历。
进行BFS遍历来找到最小移动次数。
class Solution {
public:
struct ccw{
int w,x1,y1;
ccw(int _w,int _x1,int _y1){
w=_w;
x1=_x1;
y1=_y1;
}
};
int slidingPuzzle(vector<vector<int>>& board) {
int x,y,flag=0;
for(int i=0;i<2;i++){
if(flag) break;
for(int j=0;j<3;j++){
if(board[i][j]==0){
x=i;
y=j;
flag=1;
break;
}
}
}
int ans = BFS(x,y,board);
return ans;
}
int BFS(int x,int y,vector<vector<int>> board){
map<int,int> vis;
queue<ccw> qu;
int bd=encoding(board);
if(bd==123450) return 0;
qu.push(ccw(bd,x,y));
vis[bd]=1;
vector<vector<int>> rc={{-1,0},{1,0},{0,-1},{0,1}};
int ans=0;
while(!qu.empty()){
ans++;
int mu=qu.size();
for(int i=0;i<mu;i++){
auto tp =qu.front();
qu.pop();
int x2=tp.x1,y2=tp.y1,bd2=tp.w;
vector<vector<int>> board1=coding(bd2);
for(int i=0;i<4;i++){
vector<vector<int>> board2=swap(board1,i,x2,y2);
int bd3=encoding(board2);
if(bd3==123450) return ans;
if(!vis.count(bd3)){
qu.push(ccw(bd3,x2+rc[i][0],y2+rc[i][1]));
vis[bd3]=1;
}
}
}
}
return -1;
}
vector<vector<int>> swap(vector<vector<int>> board,int status,int x,int y){
vector<vector<int>> ans;
if(status==0){
if(x-1<0) return board;
else{
int k=board[x-1][y];
board[x-1][y]=board[x][y];
board[x][y]=k;
}
}else if(status==1){
if(x+1>1) return board;
else{
int k=board[x+1][y];
board[x+1][y]=board[x][y];
board[x][y]=k;
}
}else if(status==2){
if(y-1<0) return board;
else{
int k=board[x][y-1];
board[x][y-1]=board[x][y];
board[x][y]=k;
}
}else if(status==3){
if(y+1>2) return board;
else{
int k=board[x][y+1];
board[x][y+1]=board[x][y];
board[x][y]=k;
}
}
ans = board;
return ans;
}
int encoding(const vector<vector<int>>& mat, int m = 2, int n = 3) {
int x = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
x = x * 10 + mat[i][j];
}
}
return x;
}
vector<vector<int>> coding(int x, int m = 2, int n = 3) {
vector<vector<int>> mat(m, vector<int>(n));
for (int i = m - 1; i >= 0; --i) {
for (int j = n - 1; j >= 0; --j) {
mat[i][j] = x % 10;
x = x / 10;
}
}
return mat;
}
};