|
| 1 | +/** |
| 2 | + * 864. Shortest Path to Get All Keys |
| 3 | + * https://leetcode.com/problems/shortest-path-to-get-all-keys/ |
| 4 | + * Difficulty: Hard |
| 5 | + * |
| 6 | + * You are given an m x n grid grid where: |
| 7 | + * - '.' is an empty cell. |
| 8 | + * - '#' is a wall. |
| 9 | + * - '@' is the starting point. |
| 10 | + * - Lowercase letters represent keys. |
| 11 | + * - Uppercase letters represent locks. |
| 12 | + * |
| 13 | + * You start at the starting point and one move consists of walking one space in one of the |
| 14 | + * four cardinal directions. You cannot walk outside the grid, or walk into a wall. |
| 15 | + * |
| 16 | + * If you walk over a key, you can pick it up and you cannot walk over a lock unless you have |
| 17 | + * its corresponding key. |
| 18 | + * |
| 19 | + * For some 1 <= k <= 6, there is exactly one lowercase and one uppercase letter of the first |
| 20 | + * k letters of the English alphabet in the grid. This means that there is exactly one key for |
| 21 | + * each lock, and one lock for each key; and also that the letters used to represent the keys |
| 22 | + * and locks were chosen in the same order as the English alphabet. |
| 23 | + * |
| 24 | + * Return the lowest number of moves to acquire all keys. If it is impossible, return -1. |
| 25 | + */ |
| 26 | + |
| 27 | +/** |
| 28 | + * @param {string[]} grid |
| 29 | + * @return {number} |
| 30 | + */ |
| 31 | +var shortestPathAllKeys = function(grid) { |
| 32 | + const rows = grid.length; |
| 33 | + const cols = grid[0].length; |
| 34 | + let startRow; |
| 35 | + let startCol; |
| 36 | + let totalKeys = 0; |
| 37 | + |
| 38 | + for (let i = 0; i < rows; i++) { |
| 39 | + for (let j = 0; j < cols; j++) { |
| 40 | + if (grid[i][j] === '@') { |
| 41 | + startRow = i; |
| 42 | + startCol = j; |
| 43 | + } else if (/[a-f]/.test(grid[i][j])) { |
| 44 | + totalKeys++; |
| 45 | + } |
| 46 | + } |
| 47 | + } |
| 48 | + |
| 49 | + const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; |
| 50 | + const queue = [[startRow, startCol, 0, 0]]; |
| 51 | + const visited = new Set([`${startRow},${startCol},0`]); |
| 52 | + |
| 53 | + while (queue.length) { |
| 54 | + const [row, col, keys, steps] = queue.shift(); |
| 55 | + if (keys === (1 << totalKeys) - 1) return steps; |
| 56 | + for (const [dr, dc] of directions) { |
| 57 | + const newRow = row + dr; |
| 58 | + const newCol = col + dc; |
| 59 | + |
| 60 | + if (newRow >= 0 && newRow < rows && newCol >= 0 |
| 61 | + && newCol < cols && grid[newRow][newCol] !== '#') { |
| 62 | + const cell = grid[newRow][newCol]; |
| 63 | + const newKeys = /[a-f]/.test(cell) |
| 64 | + ? keys | (1 << (cell.charCodeAt(0) - 97)) |
| 65 | + : keys; |
| 66 | + |
| 67 | + if (/[A-F]/.test(cell) && !(keys & (1 << (cell.charCodeAt(0) - 65)))) continue; |
| 68 | + const state = `${newRow},${newCol},${newKeys}`; |
| 69 | + if (!visited.has(state)) { |
| 70 | + visited.add(state); |
| 71 | + queue.push([newRow, newCol, newKeys, steps + 1]); |
| 72 | + } |
| 73 | + } |
| 74 | + } |
| 75 | + } |
| 76 | + |
| 77 | + return -1; |
| 78 | +}; |
0 commit comments