Matrix DP
Matrix (or Grid) DP problems involve finding a path or calculating a value on a 2D grid. The movement is usually restricted (e.g., only move Right or Down).
1. Unique Paths II (with Obstacles)
Problem Statement: You are a robot located at the top-left corner of an m x n grid. You can only move either down or right at any point in time. The grid contains obstacles marked as 1 and empty spaces marked as 0. How many unique paths are there to reach the bottom-right corner?
Recurrence Relation
Let dp[i][j] be the number of unique paths to reach cell (i, j).
- Base Case:
dp[0][0] = 1(if no obstacle at start). - If
grid[i][j]is an obstacle:dp[i][j] = 0. - Otherwise:
dp[i][j] = dp[i-1][j] (from top) + dp[i][j-1] (from left).
Interactive Visualizer
Click on cells to toggle obstacles (red blocks). Then click “Calculate Paths” to see how the number of paths propagates through the grid.
[!TIP] Try it yourself: Create a wall of obstacles and see how the path count drops to 0 behind it.
Code Implementation: Unique Paths II
// Java
public class UniquePathsII {
public int uniquePathsWithObstacles(int[][] obstacleGrid) {
int m = obstacleGrid.length;
int n = obstacleGrid[0].length;
int[][] dp = new int[m][n];
// Base case
if (obstacleGrid[0][0] == 0) {
dp[0][0] = 1;
}
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (obstacleGrid[i][j] == 1) {
dp[i][j] = 0;
continue;
}
if (i > 0) dp[i][j] += dp[i - 1][j];
if (j > 0) dp[i][j] += dp[i][j - 1];
}
}
return dp[m - 1][n - 1];
}
}
// Go
func UniquePathsWithObstacles(obstacleGrid [][]int) int {
m := len(obstacleGrid)
n := len(obstacleGrid[0])
dp := make([][]int, m)
for i := range dp {
dp[i] = make([]int, n)
}
if obstacleGrid[0][0] == 0 {
dp[0][0] = 1
}
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if obstacleGrid[i][j] == 1 {
dp[i][j] = 0
continue
}
if i > 0 {
dp[i][j] += dp[i-1][j]
}
if j > 0 {
dp[i][j] += dp[i][j-1]
}
}
}
return dp[m-1][n-1]
}
2. Minimum Path Sum
Problem Statement: Given a grid filled with non-negative numbers, find a path from top-left to bottom-right which minimizes the sum of all numbers along its path. You can only move down or right.
Recurrence Relation
dp[i][j] = grid[i][j] + min(dp[i-1][j], dp[i][j-1])
- Boundary conditions:
- Top row: Can only come from left.
- Left column: Can only come from top.
Code Implementation: Minimum Path Sum
// Java
public class MinPathSum {
public int minPathSum(int[][] grid) {
int m = grid.length;
int n = grid[0].length;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (i == 0 && j == 0) continue; // Start
int fromTop = (i > 0) ? grid[i - 1][j] : Integer.MAX_VALUE;
int fromLeft = (j > 0) ? grid[i][j - 1] : Integer.MAX_VALUE;
grid[i][j] += Math.min(fromTop, fromLeft);
}
}
return grid[m - 1][n - 1];
}
}
// Go
import "math"
func MinPathSum(grid [][]int) int {
m := len(grid)
n := len(grid[0])
for i := 0; i < m; i++ {
for j := 0; j < n; j++ {
if i == 0 && j == 0 {
continue
}
fromTop := math.MaxInt32
if i > 0 {
fromTop = grid[i-1][j]
}
fromLeft := math.MaxInt32
if j > 0 {
fromLeft = grid[i][j-1]
}
if fromTop < fromLeft {
grid[i][j] += fromTop
} else {
grid[i][j] += fromLeft
}
}
}
return grid[m-1][n-1]
}
3. Deep Dive Strategy Lab: Matrix Dp
Intuition Through Analogy
Think of this chapter like budget planning across months. The goal is not to memorize a fixed trick, but to repeatedly answer:
- What is the bottleneck?
- Which constraint dominates (time, memory, latency, correctness)?
- Which representation makes the bottleneck easier to eliminate?