cconnected.
Understand the pattern. Find your own way.Find your starting point
Your learning feed/Idea 125 of 218
Ideas this builds on
Extra state & 3D DP125 / 218

Shortest Path in a Grid with Obstacles Elimination

Picture

At the same square, an arrival with one removal ticket has more options than an arrival with none. Unlike the earlier right/down route-count problem, all four directions are allowed and the objective is fewest moves.

Predict

Does a three-coordinate state automatically mean a three-dimensional DP table?

Walk through the small example

No. The state says what to remember. The transition costs and dependencies decide how to explore it. Here unit-cost BFS handles the expanded state graph.

Mental model and complete Python solution

Use (row,column,tickets_left) as the visited key. Each move costs one step; entering an obstacle spends one ticket. Different resource states at the same location may have different legal continuations. BFS finalizes the first reached distance for each full state, even if the original grid has cycles. An optimal shortest route need not contain a cycle, so repeatedly charging obstacles when revisited does not exclude a necessary optimal solution.

What the function promises: The nonempty binary grid has empty start and finish cells. Move in four directions, remove at most k obstacles, and return the fewest steps or −1. Input remains unchanged.

from collections import deque

def shortest_with_removals(grid, k):
    rows, cols = len(grid), len(grid[0])
    queue = deque([(0, 0, k, 0)])
    seen = {(0, 0, k)}
    while queue:
        r, c, left, steps = queue.popleft()
        if (r, c) == (rows - 1, cols - 1):
            return steps
        for nr, nc in ((r-1,c), (r+1,c), (r,c-1), (r,c+1)):
            if not (0 <= nr < rows and 0 <= nc < cols):
                continue
            remaining = left - grid[nr][nc]
            state = (nr, nc, remaining)
            if remaining >= 0 and state not in seen:
                seen.add(state)
                queue.append((nr, nc, remaining, steps + 1))
    return -1

assert shortest_with_removals([[0,1], [1,0]], 1) == 2
assert shortest_with_removals([[0,1], [1,0]], 0) == -1
assert shortest_with_removals([[0]], 0) == 0

Work and storage: O(RC(k+1)) time and space: at most RC(k+1) states with four moves each. A dominance optimization may keep fewer states, but must compare both arrival distance and remaining budget correctly.

When to recognize it: All moves cost one, but arriving with a spare removal ticket can unlock a different future.

Check before applying it: A visited flag per square discards useful arrivals. Right/down DP also fails when the route may move back or up.

Change one rule

Two arrivals reach a square at the same or smaller distance, and one has more tickets. Can we prune the poorer arrival?

See what changes

Yes, if the richer arrival is no later. It can follow any continuation available to the poorer one. More tickets alone is not a dominance proof when reaching them took extra steps.

Connect

budget dp: Keep the resource coordinate but change the evaluation method to BFS.

Minimum Cost to Make at Least One Valid Path in a Grid: Minimizing obstacles removed is not the same objective as minimizing steps.

Problem reference: Shortest Path in a Grid with Obstacles Elimination (Hard). The walkthrough and Python solution above are original course material.