zoukankan      html  css  js  c++  java
  • 864. 获取所有钥匙的最短路径 BFS

    给定一个二维网格 grid。 "." 代表一个空房间, "#" 代表一堵墙, "@" 是起点,("a", "b", ...)代表钥匙,("A", "B", ...)代表锁。

    我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间。我们不能在网格外面行走,也无法穿过一堵墙。如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。

    假设 K 为钥匙/锁的个数,且满足 1 <= K <= 6,字母表中的前 K 个字母在网格中都有自己对应的一个小写和一个大写字母。换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁。另外,代表钥匙和锁的字母互为大小写并按字母顺序排列。

    返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。

    来源:力扣(LeetCode)
    链接:https://leetcode-cn.com/problems/shortest-path-to-get-all-keys
    著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

    class Solution {
    public:
        struct State {
            int x, y, key;
            State(int x, int y, int key):x(x), y(y), key(key){}
            State():x(0), y(0), key(0){}
        };
    
        bool vis[31][31][1 << 6];
        int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
        int ans = 0;
        int st_x, st_y;
        int cnt = 0;
    
        int shortestPathAllKeys(vector<string>& grid) {
            int n = grid.size();
            int m = grid[0].size();
    
            for (int i = 0; i < n; i++) {
                for (int j = 0; j < m; j++) {
                    if (grid[i][j] == '@') {
                        st_x = i;
                        st_y = j;
                    }
                    if (islower(grid[i][j])) {
                        cnt++;
                    }
                }
            }
    
            int mask = (1 << cnt) - 1;
            queue <State> q;
            q.push(State(st_x, st_y, 0));
            vis[st_x][st_y][0] = true;
            while (!q.empty()) {
                // 用len记录当前队列长度,不要直接使用q.size()
                int len = q.size();
                for (int k = 0; k < len; k++) {
                    auto cur = q.front();q.pop();
                    // 如果所有锁都已经解开,则返回答案
                    if ((cur.key & mask) == mask) {
                        return ans;
                    }
                    for (int i = 0; i < 4; i++) {
                        int tx = cur.x + dir[i][0];
                        int ty = cur.y + dir[i][1];
                        if (tx < 0 || tx >= n || ty < 0 || ty >= m) {
                            continue;
                        }
                        char ch = grid[tx][ty];
                        // 如果遇到墙
                        if (ch == '#') {
                            continue;
                        }
                        // 如果是锁
                        if (isupper(ch)) {
                            // 如果当前没有解对应所的钥匙,则没法走,返回
                            if ( ((cur.key >> (ch - 'A') & 1) != 1) {
                                continue;
                            }
                        }
    
                        // 保存当前状态
                        int temp = cur.key;
                        // 如果是钥匙,则更新状态
                        if (islower(ch)) {
                            temp |= (1 << (ch - 'a'));
                        }
                        if (vis[tx][ty][temp]) {
                            continue;
                        }
                        vis[tx][ty][temp] = true;
                        q.push(State(tx, ty, temp));
                    }
                }
                ans++;
            }
            return -1;
        }
    };
    
  • 相关阅读:
    默比乌斯函数
    勒让德符号相关
    微积分入门("SX"T版)
    分治法求2n个数的中位数
    SSM框架学习之高并发秒杀业务--笔记1-- 项目的创建和依赖
    10月9日Android学习笔记:活动与服务之间的通信
    高精度加法
    Windows环境下多线程编程原理与应用读书笔记(4)————线程间通信概述
    郁闷
    素数链
  • 原文地址:https://www.cnblogs.com/xgbt/p/15726010.html
Copyright © 2011-2022 走看看