2Brute2Best
🔥0
01

Paths in a grid (DP — Grid Sub-pattern)

dp[r][c] = the number of ways (or the cheapest cost) to reach (r, c), built from the cells you could have come from.

Signals in the problem statement
  • ›

    "move only right or down"

  • ›

    "number of unique paths"

  • ›

    "minimum path sum", "falling path"

  • ›

    "obstacles"

  • ›

    a triangle of numbers

What makes it different

Ask which cells could the last move come from? Two (top, left) for corner-to-corner; three (up-left, up, up-right) for falling paths; two below for a triangle filled bottom-up.

Questions

ordered from “learn the idea” to “recognise it without help”
  1. 1
    Unique Paths
    Basic Anchor·LeetCode #62
    Medium
  2. 2
    Unique Paths II
    Basic Reinforcement·LeetCode #63
    Medium
  3. 3
    Minimum Path Sum
    Slight Variation·LeetCode #64
    Medium
  4. 4
    Triangle
    Medium·LeetCode #120
    Medium
  5. 5
    Minimum Falling Path Sum
    Pattern Transfer·LeetCode #931
    Medium

Template

paths-template.cpp
// Grid paths in one row: moves go right or down only.
// Before the update dp[c] is the cell ABOVE; dp[c - 1] is already the new cell to the LEFT.

// Number of ways from the top-left to the bottom-right (1 = blocked).
long long countPaths(const vector<vector<int>>& blocked) {
    int m = blocked.size(), n = blocked[0].size();
    vector<long long> dp(n, 0);
    dp[0] = 1;
    for (int r = 0; r < m; r++)
        for (int c = 0; c < n; c++) {
            if (blocked[r][c]) dp[c] = 0;            // no path goes through an obstacle
            else if (c > 0) dp[c] += dp[c - 1];      // above (old dp[c]) + left (dp[c - 1])
        }
    return dp[n - 1];
}

// Cheapest path: same order, min instead of +.
int minPathCost(const vector<vector<int>>& cost) {
    int m = cost.size(), n = cost[0].size();
    vector<int> dp(n, INT_MAX);
    dp[0] = 0;
    for (int r = 0; r < m; r++)
        for (int c = 0; c < n; c++) {
            int best = dp[c];                        // from above
            if (c > 0) best = min(best, dp[c - 1]);  // from the left
            dp[c] = best + cost[r][c];
        }
    return dp[n - 1];
}
Remember this · DP — Grid
Trigger
Move only right/down, count paths, minimum path cost, largest square of 1s.
Think
To reach cell (r, c), which cells could I have come from?
Key question
What does dp[r][c] mean, and what are the first row/column?