|
| 1 | +/** |
| 2 | + * 749. Contain Virus |
| 3 | + * https://leetcode.com/problems/contain-virus/ |
| 4 | + * Difficulty: Hard |
| 5 | + * |
| 6 | + * A virus is spreading rapidly, and your task is to quarantine the infected area by |
| 7 | + * installing walls. |
| 8 | + * |
| 9 | + * The world is modeled as an m x n binary grid isInfected, where isInfected[i][j] == 0 |
| 10 | + * represents uninfected cells, and isInfected[i][j] == 1 represents cells contaminated |
| 11 | + * with the virus. A wall (and only one wall) can be installed between any two 4-directionally |
| 12 | + * adjacent cells, on the shared boundary. |
| 13 | + * |
| 14 | + * Every night, the virus spreads to all neighboring cells in all four directions unless |
| 15 | + * blocked by a wall. Resources are limited. Each day, you can install walls around only one |
| 16 | + * region (i.e., the affected area (continuous block of infected cells) that threatens the |
| 17 | + * most uninfected cells the following night). There will never be a tie. |
| 18 | + * |
| 19 | + * Return the number of walls used to quarantine all the infected regions. If the world will |
| 20 | + * become fully infected, return the number of walls used. |
| 21 | + */ |
| 22 | + |
| 23 | +/** |
| 24 | + * @param {number[][]} isInfected |
| 25 | + * @return {number} |
| 26 | + */ |
| 27 | +var containVirus = function(isInfected) { |
| 28 | + const verticalBarriers = new Set(); |
| 29 | + const horizontalBarriers = new Set(); |
| 30 | + const grid = isInfected; |
| 31 | + const rows = grid.length; |
| 32 | + const cols = grid[0].length; |
| 33 | + const directions = [[-1, 0, -cols, -cols], [1, 0, cols, 0], [0, -1, -1, -1], [0, 1, 1, 0]]; |
| 34 | + let target; |
| 35 | + let nextState; |
| 36 | + let maxThreat; |
| 37 | + let threatenedCells; |
| 38 | + let nextVertical; |
| 39 | + let nextHorizontal; |
| 40 | + let verticalWalls; |
| 41 | + let horizontalWalls; |
| 42 | + let startRow; |
| 43 | + let startCol; |
| 44 | + |
| 45 | + while (true) { |
| 46 | + target = 1; |
| 47 | + nextState = 2; |
| 48 | + maxThreat = 0; |
| 49 | + grid.forEach((row, r) => row.forEach((cell, c) => cell && exploreRegion(r, c))); |
| 50 | + if (maxThreat === 0) return verticalBarriers.size + horizontalBarriers.size; |
| 51 | + target = 2; |
| 52 | + nextState = 0; |
| 53 | + traverseRegion(startRow, startCol); |
| 54 | + verticalWalls.forEach(pos => verticalBarriers.add(pos)); |
| 55 | + horizontalWalls.forEach(pos => horizontalBarriers.add(pos)); |
| 56 | + nextState = 1; |
| 57 | + threatenedCells = new Set(); |
| 58 | + grid.forEach((row, r) => row.forEach((cell, c) => cell && traverseRegion(r, c))); |
| 59 | + threatenedCells.forEach(pos => grid[Math.floor(pos / cols)][pos % cols] = 1); |
| 60 | + } |
| 61 | + |
| 62 | + function exploreRegion(row, col) { |
| 63 | + threatenedCells = new Set(); |
| 64 | + nextVertical = new Set(); |
| 65 | + nextHorizontal = new Set(); |
| 66 | + traverseRegion(row, col); |
| 67 | + if (threatenedCells.size < maxThreat) return; |
| 68 | + maxThreat = threatenedCells.size; |
| 69 | + verticalWalls = nextVertical; |
| 70 | + horizontalWalls = nextHorizontal; |
| 71 | + startRow = row; |
| 72 | + startCol = col; |
| 73 | + } |
| 74 | + |
| 75 | + function traverseRegion(row, col) { |
| 76 | + if (grid[row][col] !== target) return; |
| 77 | + grid[row][col] = nextState; |
| 78 | + const position = cols * row + col; |
| 79 | + for (let i = 0; i < 4; i++) { |
| 80 | + const [deltaRow, deltaCol, threatOffset, wallOffset] = directions[i]; |
| 81 | + const newRow = row + deltaRow; |
| 82 | + const newCol = col + deltaCol; |
| 83 | + if (newRow < 0 || newRow === rows || newCol < 0 || newCol === cols) continue; |
| 84 | + traverseRegion(newRow, newCol); |
| 85 | + if (grid[newRow][newCol] |
| 86 | + || (deltaRow ? verticalBarriers : horizontalBarriers).has(position + wallOffset)) continue; |
| 87 | + if (nextState) threatenedCells.add(position + threatOffset); |
| 88 | + if (nextState > 1) (deltaRow ? nextVertical : nextHorizontal).add(position + wallOffset); |
| 89 | + } |
| 90 | + } |
| 91 | +}; |
0 commit comments