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;
    }
};
上一篇:变量、常量、作用域


下一篇:c++处理字符串string.find()与string::npos