
Data Structure
Networking
RDBMS
Operating System
Java
MS Excel
iOS
HTML
CSS
Android
Python
C Programming
C++
C#
MongoDB
MySQL
Javascript
PHP
- Selected Reading
- UPSC IAS Exams Notes
- Developer's Best Practices
- Questions and Answers
- Effective Resume Writing
- HR Interview Questions
- Computer Glossary
- Who is Who
Shortest Path to Get All Keys in C++
Suppose we have a grid. There are few symbols. "." is indicating empty cell, "#" is for wall, "@" is for starting point, ("a", "b", ...) all are keys, and ("A", "B", ...) all are locks. We will start from the starting point, and one move consists of walking one space in one of the 4 directions (left, right, top, bottom). We will not go outside the grid, and there are walls to block our way. If we walk over a key, we pick it up. We can't walk over a lock unless we have the corresponding key.
For each lock like A, B etc we have keys like a, b, etc, so locks are same letter in uppercase letters and keys are same with lower case letters.
We have to find the lowest number of moves to acquire all keys. If it's impossible, return -1.
So, if the input is like ["@.a.#","###.#","b.A.B"], then the output will be 8
To solve this, we will follow these steps −
n := number of rows, m := number of columns
Define an array start of size 3
cnt := 0
-
for initialize i := 0, when i < n, update (increase i by 1), do −
-
for initialize j := 0, when j < m, update (increase j by 1), do −
-
if grid[i, j] is same as '@', then −
start[1] := i, start[2] := j
-
if grid[i, j] >= 'a' and grid[i, j] <= 'f', then −
cnt := maximum of cnt and grid[i, j] - 'a' + 1
-
-
Define one set visited
req := 2^(cnt - 1)
Define one queue q of arrays
insert start into q
insert start into visited
level := 0
-
while (not q is empty), do −
sz := size of q
-
while sz is non-zero, decrease sz after each iteration, do −
Define an array curr := front element of q
delete element from q
key := curr[0]
-
if key is same as req, then −
return level
x := curr[1], y := curr[2]
prevKey := key
-
for initialize i := 0, when i < 4, update (increase i by 1), do −
nx := x + dir[i, 0], ny := y + dir[i, 1]
key := prevKey
-
if nx >= 0 and ny >= 0 and nx < n and ny < m, then −
-
if grid[nx, ny] is same as '#', then −
Ignore following part, skip to the next iteration
-
if grid[nx, ny] >= 'a' and grid[nx, ny] <= 'f', then −
key := key OR (2^(grid[nx, ny] - ASCII of 'a'))
-
if grid[nx, ny] >= 'A' and grid[nx, ny] <= 'F', then −
-
if (shift key to the right (grid[nx, ny] - ASCII of 'A') times AND 1) is same as 0, then −
Ignore following part, skip to the next iteration
-
Define an array state({ key, nx, ny })
-
if state is in visited, then −
Ignore following part, skip to the next iteration
insert state into q
insert state into visited
-
(increase level by 1)
return -1
Let us see the following implementation to get better understanding −
Example
#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)); }
Input
{"@.a.#","###.#","b.A.B"}
Output
8