题目描述:
二维矩阵,小写字母对应大写字母的钥匙。有墙和门,不能穿过墙,遇见门时只有有钥匙才能过去。问最少走多少步能拿到所有的钥匙。
思路:
bfs,开始是像普通bfs一样,记录每个位置的步数。后来试图标记钥匙的个数。
原来是标记拿到的所有钥匙。。。。因为钥匙最多只有6把,可以用位运算来判断当前是否有这把钥匙。
代码:
class Solution {
public:
int shortestPathAllKeys(vector<string>& grid) {
int n = grid.size(), m = grid[0].size();
int stx, sty;
int cnt = 0;
for (int i=0; i<n; ++i) {
for (int j=0; j<m; ++j) {
if (grid[i][j] == '@') {
stx = i, sty = j;
}else if (grid[i][j] >= 'a' && grid[i][j] <= 'f') {
cnt++;
}
}
}
vector<vector<vector<int>>> step(n, vector<vector<int>>(m, vector<int>((1<<cnt), INT_MAX/2)));
step[stx][sty][0] = 0;
queue<tuple<int, int, int>> que;
que.push({stx, sty, 0});
vector<int> dir {1, 0, -1, 0, 1};
while(!que.empty()) {
auto cur = que.front();
que.pop();
int x = get<0>(cur);
int y = get<1>(cur);
int s = get<2>(cur);
if (s == ((1<<cnt)-1)) return step[x][y][s];
for (int i=0; i<4; ++i) {
int nx = x + dir[i];
int ny = y + dir[i+1];
if (nx < 0 || nx >= n || ny < 0 || ny >= m) continue;
if (grid[nx][ny] == '#') continue;
if (grid[nx][ny] == '.' || grid[nx][ny] == '@') {
if (step[nx][ny][s] > step[x][y][s]+1) {
step[nx][ny][s] = step[x][y][s] + 1;
que.push({nx, ny, s});
}
}
if (grid[nx][ny] >= 'a' && grid[nx][ny] <= 'f') {
int key = grid[nx][ny] - 'a';
int ns = (s | (1<<key));
if (step[nx][ny][ns] > step[x][y][s] + 1) {
step[nx][ny][ns] = step[x][y][s] + 1;
que.push({nx, ny, ns});
}
}
if (grid[nx][ny] >= 'A' && grid[nx][ny] <= 'F') {
int key = grid[nx][ny] - 'A';
if ((s & (1<<key)) != 0 && step[nx][ny][s] > step[x][y][s] + 1) {
step[nx][ny][s] = step[x][y][s] + 1;
que.push({nx, ny, s});
}
}
}
}
return -1;
}
};
一上午:我想要小米手环。
经历了1s售空。
=================================================================
第二次写。主要还是因为步数的更新和状态有关。