2020-5 leetcode 773. 滑动谜题

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;
    }

};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值