Dynamic Programming (1D, 2D, Knapsack, Range DP)
Dynamic Programming (1D, 2D, Knapsack, Range DP)
Problem Scenario / Typical Use Case
Imagine you are managing budget allocation across multiple projects and need to maximize total value without exceeding limits.
Naively trying all combinations grows exponentially with the number of projects. Dynamic Programming (DP) provides a systematic way to solve overlapping subproblems efficiently by storing intermediate results.
Basic Idea
Dynamic Programming involves:
- Identifying subproblems: Break the main problem into smaller, overlapping subproblems.
- Storing solutions: Use a table (1D, 2D, or higher) to save results of subproblems.
- Building up the solution: Combine stored subproblem results to solve the original problem.
Variants include:
- 1D DP: Problems like Fibonacci, climbing stairs, or 1D array optimization.
- 2D DP: Grid-based problems, like minimum path sum.
- Knapsack DP: Classic resource allocation with weights and values.
- Range DP: Subarray or interval-based problems where solution depends on ranges.
Advantages
- Efficiency: Converts exponential brute-force into polynomial-time solutions.
- Reusability: Subproblem solutions are reused, reducing redundant computation.
- Versatility: Applicable to optimization, counting, and decision-making problems.
Limitations / Considerations
- Memory Usage: Storing subproblem results can be costly in high dimensions.
- Complexity Analysis: Requires careful planning of state representation and transitions.
- Not Always Intuitive: Formulating subproblems and recurrence relations can be challenging.
Practical Examples / Thought Triggers
- Knapsack Problem: Maximize value given weight limits.
- Grid Path Sum: Calculate minimum/maximum paths in 2D grids.
- Interval DP: Solve problems over ranges, such as matrix chain multiplication.
Thought Triggers:
- What should my DP state represent?
- Can the state dimension be reduced (e.g., 1D instead of 2D) to save space?
- Can I combine DP with other patterns like Greedy or Binary Search for optimization?
Implementation Example
Here’s a Python example for 1D Knapsack problem (0/1 Knapsack):
def knapsack(values, weights, W):
n = len(values)
dp = [0] * (W + 1)
for i in range(n):
for w in range(W, weights[i] - 1, -1):
dp[w] = max(dp[w], dp[w - weights[i]] + values[i])
return dp[W]
# Example usage
values = [60, 100, 120]
weights = [10, 20, 30]
capacity = 50
print(knapsack(values, weights, capacity))
# Output: 220
This demonstrates dynamic programming with 1D array optimization, efficiently solving the knapsack problem.
Related Articles
- Divide & Conquer: Some DP problems can be thought of as memoized divide & conquer.
- Greedy Algorithms: Compare DP vs greedy to determine optimality requirements.
- Range DP / Matrix Traversal: DP can generalize to interval and grid-based problems.