zoukankan      html  css  js  c++  java
  • Leetcode 多维度dp+优先队列+bfs

    LC 1263. 推箱子

    题目:推箱子中箱子的最少移动步数,人的次数不算

    方法一:优先队列+BFS

    Node{步数,人x,人y,箱子x,箱子y},优先队列按步数从小到大排序,每次取最小的出来更新(相当于Dijkstra变形),vis记录节点是否访问。
    也可以完全用dis数据,记录达到某状态的最小距离,按dis更新,那就是完全Dijkstra了
    人移动可以推箱子,也可能不推,判断一下,没有推箱子的话步数不变。

    class Solution {
    public:
        bool vis[25][25][25][25];
        const int dx[4] = {-1, 0, 1, 0};
        const int dy[4] = {0, 1, 0, -1};
        int minPushBox(vector<vector<char>>& grid) {
            memset(vis, 0, sizeof(vis));
            priority_queue<vector<int>, vector<vector<int>>, greater<vector<int>>> pq; // 取步数最小的
            int row = grid.size(), col = grid[0].size();
            int ax, ay, bx, by, ex, ey;
            for(int i = 0;i < row;i++) {
                for(int j = 0;j < col;j++) {
                    if(grid[i][j] == 'S') {
                        ax = i, ay = j;
                        grid[i][j] = '.';
                    }
                    if(grid[i][j] == 'B') {
                        bx = i, by = j;
                        grid[i][j] = '.';
                    }
                    if(grid[i][j] == 'T') {
                        ex = i, ey = j;
                    }
                }
            }
            pq.push({0, ax, ay, bx, by}); // 步数,人,箱子
            vis[ax][ay][bx][by] = true;
            while(!pq.empty()) {
                auto p = pq.top();pq.pop();
                // cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3] << " " << p[4] << endl;
                if(p[3] == ex && p[4] == ey)  return p[0];
                for(int i = 0;i < 4;i++) {
                    int nax = p[1]+dx[i], nay = p[2]+dy[i];  // 人
                    if(nax < 0 || nax >= row || nay < 0 || nay >= col || grid[nax][nay] == '#')  continue;
                    int nbx = (nax == p[3] && nay == p[4] ? p[3]+dx[i] : p[3]); // 箱子要么随人走,要么不动
                    int nby = (nax == p[3] && nay == p[4] ? p[4]+dy[i] : p[4]);
                    if(nbx < 0 || nbx >= row || nby < 0 || nby >= col || grid[nbx][nby] == '#')  continue;
                    int w = (nax == p[3] && nay == p[4]);  // 箱子移动了记1
                    if(!vis[nax][nay][nbx][nby]) {
                        vis[nax][nay][nbx][nby] = true;
                        pq.push({p[0]+w, nax, nay, nbx, nby});  
                    }
                }
            }
            return -1;
        }
    };
    

    方法二:01队列+BFS

    由于步数要么加1,要么不变,即只用01两种。可以用01队列代替优先队列,也就是01BFS。

    class Solution {
    public:
        bool vis[25][25][25][25];
        const int dx[4] = {-1, 0, 1, 0};
        const int dy[4] = {0, 1, 0, -1};
        int minPushBox(vector<vector<char>>& grid) {
            memset(vis, 0, sizeof(vis));
            deque<vector<int>> pq; // 01队列
            int row = grid.size(), col = grid[0].size();
            int ax, ay, bx, by, ex, ey;
            for(int i = 0;i < row;i++) {
                for(int j = 0;j < col;j++) {
                    if(grid[i][j] == 'S') {
                        ax = i, ay = j;
                        grid[i][j] = '.';
                    }
                    if(grid[i][j] == 'B') {
                        bx = i, by = j;
                        grid[i][j] = '.';
                    }
                    if(grid[i][j] == 'T') {
                        ex = i, ey = j;
                    }
                }
            }
            pq.push_front({0, ax, ay, bx, by}); // 步数,人,箱子
            vis[ax][ay][bx][by] = true;
            while(!pq.empty()) {
                auto p = pq.front();pq.pop_front();
                // cout << p[0] << " " << p[1] << " " << p[2] << " " << p[3] << " " << p[4] << endl;
                if(p[3] == ex && p[4] == ey)  return p[0];
                for(int i = 0;i < 4;i++) {
                    int nax = p[1]+dx[i], nay = p[2]+dy[i];  // 人
                    if(nax < 0 || nax >= row || nay < 0 || nay >= col || grid[nax][nay] == '#')  continue;
                    int nbx = (nax == p[3] && nay == p[4] ? p[3]+dx[i] : p[3]); // 箱子要么随人走,要么不动
                    int nby = (nax == p[3] && nay == p[4] ? p[4]+dy[i] : p[4]);
                    if(nbx < 0 || nbx >= row || nby < 0 || nby >= col || grid[nbx][nby] == '#')  continue;
                    int w = (nax == p[3] && nay == p[4]);  // 箱子移动了记1
                    if(!vis[nax][nay][nbx][nby]) {
                        vis[nax][nay][nbx][nby] = true;
                        if(w == 0)  pq.push_front({p[0], nax, nay, nbx, nby});  
                        else  pq.push_back({p[0]+w, nax, nay, nbx, nby});  
                    }
                }
            }
            return -1;
        }
    };
    
    个性签名:时间会解决一切
  • 相关阅读:
    产品经理的未来在哪里
    如何打造一款成功的产品
    彻底解决Android 应用方法数不能超过65K的问题
    MVC,MVP 和 MVVM 的图示
    oracle最高账号sys的密码认证模式
    Android开发者必须深入学习的10个应用开源项目
    Android程序完全退出的三种方法
    Android-监听网络状态
    Android开发图片分辨率问题解决方案
    Android清除本地数据缓存代码
  • 原文地址:https://www.cnblogs.com/lfri/p/15795789.html
Copyright © 2011-2022 走看看