开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第6天,点击查看活动详情
力扣——864. 获取所有钥匙的最短路径
864. 获取所有钥匙的最短路径
给定一个二维网格 grid ,其中:
- '.' 代表一个空房间
- '#' 代表一堵
- '@' 是起点
- 小写字母代表钥匙
- 大写字母代表锁
我们从起点开始出发,一次移动是指向四个基本方向之一行走一个单位空间。我们不能在网格外面行走,也无法穿过一堵墙。如果途经一个钥匙,我们就把它捡起来。除非我们手里有对应的钥匙,否则无法通过锁。
假设 k 为 钥匙/锁 的个数,且满足 1 <= k <= 6,字母表中的前 k 个字母在网格中都有自己对应的一个小写和一个大写字母。换言之,每个锁有唯一对应的钥匙,每个钥匙也有唯一对应的锁。另外,代表钥匙和锁的字母互为大小写并按字母顺序排列。
返回获取所有钥匙所需要的移动的最少次数。如果无法获取所有钥匙,返回 -1 。
示例 1:
输入:grid = ["@.a.#","###.#","b.A.B"]
输出:8
解释:目标是获得所有钥匙,而不是打开所有锁。
示例 2:
输入:grid = ["@..aA","..B#.","....b"]
输出:6
提示:
m == grid.lengthn == grid[i].length1 <= m, n <= 30grid[i][j]只含有'.','#','@','a'-``'f``'以及'A'-'F'- 钥匙的数目范围是
[1, 6] - 每个钥匙都对应一个 不同 的字母
- 每个钥匙正好打开一个对应的锁
问题解析
很正常的BFS。
大致思路就是BFS的过程中记录拿到钥匙的情况,当遇到锁的情况只要看有没有对应的钥匙就可以知道能不能走过,当拿到所有钥匙后返回步数,如果BFS结束了也没有返回步数,说明拿不到全部的钥匙,返回-1。
至于记录拿到钥匙,因为钥匙最多只有6个,我们可以用二进制的方式来记录状态,二进制下初始为000000,0表示第i个钥匙没拿到,1表示拿到了,当我们拿到哪个钥匙后,就把哪个位置的二进制变为1。遇到锁了只要看对应位置的二进制是否为1即可。
用一个三维数组st记录bfs走过的位置情况,st[i] [j] [k]表示是否以钥匙状态为k时,走到第i行第j列。
AC代码
class Solution {
public:
int dx[4] = { 1,0,-1,0 }, dy[4] = { 0,1,0,-1 };
int st[50][50][100];
int shortestPathAllKeys(vector<string>& grid) {
int cnt = 0, x, y, n = grid.size(), m = grid[0].size();
for (int i = 0; i < n; i++)
{
for (int j = 0; j < m; j++)
{
if (grid[i][j] >= 'a' && grid[i][j] <= 'z')cnt++;
else if (grid[i][j] == '@')x = i, y = j;
}
}
int res = (1 << cnt) - 1;
queue<vector<int>>que;
//第一个0表示钥匙状态,第2个0表示走过的步数
que.push({ x,y,0,0 });
st[x][y][0] = 1;
while (!que.empty())
{
int len = que.size();
for (int i = 0; i < len; i++)
{
x = que.front()[0], y = que.front()[1];
int num = que.front()[2], ans = que.front()[3];
que.pop();
if (num == res)return ans;
for (int j = 0; j < 4; j++)
{
int a = dx[j] + x, b = dy[j] + y;
if (a >= 0 && a < n && b >= 0 && b < m && grid[a][b] != '#' && !st[a][b][num])
{
//如果遇到锁的位置,则看也没有对应的钥匙,如果没有就走不到这个位置
if (grid[a][b] >= 'A' && grid[a][b] <= 'Z' && !((num >> (grid[a][b] - 'A')) & 1))
continue;
//如果遇到钥匙,改变所持钥匙的状态
else if (grid[a][b] >= 'a' && grid[a][b] <= 'z' && !((num >> (grid[a][b] - 'a')) & 1))
{
que.push({ a,b,num + (1 << (grid[a][b] - 'a')),ans + 1 });
st[a][b][num + (1 << (grid[a][b] - 'a'))] = 1;
}
else
{
que.push({ a,b,num,ans + 1 });
st[a][b][num] = 1;
}
}
}
}
}
return -1;
}
};