03
Grid shortest path (Graph BFS / DFS Sub-pattern)
Fewest steps from a start cell to a target cell (or to any exit) in a grid where every step costs the same.
Signals in the problem statement
- ›
"shortest path" / "minimum steps" in a grid of open and blocked cells
- ›
"nearest exit"
- ›
"you may remove up to k obstacles"
What makes it different
Nearest Exit is plain BFS that stops at the first border cell that isn't the entrance. Shortest Path in Binary Matrix moves in 8 directions and counts cells, not moves. Obstacle Elimination adds the removals left to the state, so the same cell can be visited again with more removals in hand.
Questions
ordered from “learn the idea” to “recognise it without help”- 1Nearest Exit from Entrance in MazeWalkthroughMediumBasic Anchor·LeetCode #1926
- 2Shortest Path in Binary MatrixWalkthroughMediumBasic Reinforcement·LeetCode #1091
- 3Shortest Path in a Grid with Obstacles EliminationWalkthroughHardSlight Variation·LeetCode #1293
Template
grid-bfs-template.cpp
// Shortest path in an unweighted grid: BFS from the start; the first time we pop the target is the answer.
int shortestPath(const vector<vector<int>>& grid, pair<int, int> start, pair<int, int> target) { // 0 = open, 1 = wall
int R = grid.size(), C = grid[0].size();
if (grid[start.first][start.second] || grid[target.first][target.second]) return -1;
vector<vector<int>> dist(R, vector<int>(C, -1));
queue<pair<int, int>> q;
dist[start.first][start.second] = 0;
q.push(start);
int dr[4] = {1, -1, 0, 0}, dc[4] = {0, 0, 1, -1};
while (!q.empty()) {
auto [r, c] = q.front(); q.pop();
if (make_pair(r, c) == target) return dist[r][c];
for (int d = 0; d < 4; d++) {
int nr = r + dr[d], nc = c + dc[d];
if (nr < 0 || nc < 0 || nr >= R || nc >= C || grid[nr][nc] || dist[nr][nc] != -1) continue;
dist[nr][nc] = dist[r][c] + 1; // mark when PUSHED, not when popped
q.push({nr, nc});
}
}
return -1;
}Remember this · Graph BFS / DFS
Trigger
Grid of cells, islands, regions, "minimum steps", transformations between states, connected components.
Think
What is a node, what is an edge, and do I need the shortest path or just reachability?
Key question
How do I mark visited so I never process a node twice?