假设我们有一个网格。符号很少。“.” 表示空单元格,“#”表示墙,“ @”表示起点,(“ a”,“ b”,...)都是键,而(“ A”,“ B”,... )都是锁。我们将从起点开始,一招包括在四个方向(左,右,上,下)之一上行走一个空间。我们不会走出网格,并且有墙挡住我们的路。如果我们走过一把钥匙,我们会捡起它。除非我们有相应的钥匙,否则我们不能走过一把锁。
对于像A,B等的每个锁,我们都有像a,b等的键,因此锁在大写字母中是相同的字母,而在小写字母中则相同。
让我们看下面的实现以更好地理解-
#include <bits/stdc++.h> using namespace std; int dir[4][2] = {{1, 0}, {-1, 0}, {0, -1}, {0, 1}}; class Solution { public: int shortestPathAllKeys(vector<string>& grid) { int n = grid.size(); int m = grid[0].size(); vector<int> start(3); int cnt = 0; for (int i = 0; i < n; i++) { for (int j = 0; j < m; j++) { if (grid[i][j] == '@') { start[1] = i; start[2] = j; } if (grid[i][j] >= 'a' && grid[i][j] <= 'f') { cnt = max(cnt, grid[i][j] - 'a' + 1); } } } set<vector<int> > visited; int req = (1 << cnt) - 1; queue<vector<int> > q; q.push(start); visited.insert(start); int level = 0; while (!q.empty()) { int sz = q.size(); while (sz--) { vector<int> curr = q.front(); q.pop(); int key = curr[0]; if (key == req) return level; int x = curr[1]; int y = curr[2]; int nx, ny; int prevKey = key; for (int i = 0; i < 4; i++) { nx = x + dir[i][0]; ny = y + dir[i][1]; key = prevKey; if (nx >= 0 && ny >= 0 && nx < n && ny < m) { if (grid[nx][ny] == '#') continue; if (grid[nx][ny] >= 'a' && grid[nx][ny] <= 'f') { key |= (1 << (grid[nx][ny] - 'a')); } if (grid[nx][ny] >= 'A' && grid[nx][ny] <= 'F') { if (((key >> (grid[nx][ny] - 'A')) & 1) == 0) continue; } vector<int> state({ key, nx, ny }); if (visited.count(state)) continue; q.push(state); visited.insert(state); } } } level++; } return -1; } }; main(){ Solution ob; vector<string> v = {"@.a.#","###.#","b.A.B"}; cout << (ob.shortestPathAllKeys(v)); }
{"@.a.#","###.#","b.A.B"}
输出结果
8