From 3114866943cc0ab95554e91f18aa43490dc5c6fb Mon Sep 17 00:00:00 2001 From: euchangxian Date: Thu, 21 Nov 2024 12:32:09 +0800 Subject: [PATCH] feat(simulation): Add 2257 A little difficult to recognize when a simpler solution is necessary, and sufficient. --- .../Solution.cpp | 96 +++++++++++++++++++ README.md | 1 + 2 files changed, 97 insertions(+) create mode 100644 C++/2257-CountUnguardedCellsInTheGrid/Solution.cpp diff --git a/C++/2257-CountUnguardedCellsInTheGrid/Solution.cpp b/C++/2257-CountUnguardedCellsInTheGrid/Solution.cpp new file mode 100644 index 0000000..79d7587 --- /dev/null +++ b/C++/2257-CountUnguardedCellsInTheGrid/Solution.cpp @@ -0,0 +1,96 @@ +#include +#include +#include +#include +#include + +class Solution { + private: + enum State { + UNGUARDED = 0, + GUARDED = 1, + GUARD = 2, + WALL = 3, + }; + + const std::array, 4> directions{{ + {0, 1}, + {1, 0}, + {0, -1}, + {-1, 0}, + }}; + + void guardCardinal(std::vector>& grid, int r, int c) { + // DFS from [r, c] + for (auto [dr, dc] : directions) { + int nr = r + dr; + int nc = c + dc; + + while (nr >= 0 && nc >= 0 && nr < grid.size() && nc < grid[0].size() && + grid[nr][nc] != State::GUARD && grid[nr][nc] != State::WALL) { + grid[nr][nc] = State::GUARDED; + nr += dr; + nc += dc; + } + } + } + + public: + int countUnguarded(int m, + int n, + std::vector>& guards, + std::vector>& walls) { + // m * n grid. + // guard[i]/walls[j] = [row, col] => position of ith/jth guard/wall + // Guard can see every cell in the 4 cardinal direction, unless obstructed + // by a Wall or another Guard. + // A cell is guarded if there is at least one Guard who can see it. + // Return number of unoccupied cells that are not guarded. + // + // Seems like Union Find. If there is a Guard in the cardinal direction of + // a cell, then Cell = Guarded. + // Not trivial to determine that though. + // E.g., consider the case below, where a Cell is not in the cardinal + // direction of a Guard, but is beside a guarded cell. Naive UF would mean + // that the Cell is also considered Guarded. + // _ _ ... + // G ... + // ... + // What about collecting the [r, c] of each Guard and Wall into their own + // (Multi-)Sets. + // When at a Cell, check its [r, c]. + // WLOG, trivially, if either its row or column matches a Guard and no + // Walls, it is Guarded. + // If it matches a Guard and a Wall, determine if the Wall obstructs the + // Guard. + // The problem is the multi-set nature, which would require the Guard/Wall + // with the closest distance to the current Cell. + std::vector> grid(m, std::vector(n)); + + for (auto& guard : guards) { + int r = guard[0], c = guard[1]; + grid[r][c] = State::GUARD; + } + + for (auto& wall : walls) { + int r = wall[0], c = wall[1]; + grid[r][c] = State::WALL; + } + + for (auto& guard : guards) { + int r = guard[0], c = guard[1]; + guardCardinal(grid, r, c); + } + + auto isUnguarded = [](int state) -> bool { + return state == State::UNGUARDED; + }; + + int unguarded = 0; + for (auto& row : grid) { + unguarded += std::count_if(row.begin(), row.end(), isUnguarded); + } + + return unguarded; + } +}; diff --git a/README.md b/README.md index c94c778..3afaced 100644 --- a/README.md +++ b/README.md @@ -454,6 +454,7 @@ Now solving in C++. Like it. | 2220 | MinimumBitFlipsToConvertNumber | [![C++](assets/c++.svg)](C++/2220-MinimumBitFlipsToConvertNumber/Solution.cpp) | | 2246 | LongestPathWithDifferentAdjacentCharacters | [![C++](assets/c++.svg)](C++/2246-LongestPathWithDifferentAdjacentCharacters/Solution.cpp) | | 2254 | DesignVideoSharingPlatform | [![C++](assets/c++.svg)](C++/2254-DesignVideoSharingPlatform/Solution.cpp) | +| 2257 | CountUnguardedCellsInTheGrid | [![C++](assets/c++.svg)](C++/2257-CountUnguardedCellsInTheGrid/Solution.cpp) | | 2275 | LargestCombinationWithBitwiseANDGreaterThanZero | [![C++](assets/c++.svg)](C++/2275-LargestCombinationWithBitwiseANDGreaterThanZero/Solution.cpp) | | 2285 | MaximumTotalImportanceOfRoads | [![C++](assets/c++.svg)](C++/2285-MaximumTotalImportanceOfRoads/Solution.cpp) | | 2290 | MinimumObstacleRemovalToReachCorner | [![C++](assets/c++.svg)](C++/2290-MinimumObstacleRemovalToReachCorner/Solution.cpp) |