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