Dynamic programming is a programming technique developed by Richard Bellman in the 1950s. It is the "smarter" version of the brute-force approach as it stores the results of sub-problems so they can be retrieved when needed later. The recursive relationship that represents the equation is called the Bellman equation. This technique reduces the time complexity of an exponential to a polynomial.
The process of eliminating repetitive computation is called memoization (not a typo haha).
Weighted Interval Scheduling
Problem definition
Given jobs where every job is represented by start time, finish time, and a value:
Index
1 |--- value=1 --|
2 |-------- value=3 -------|
3 |--- value=1 --|
0----1----2----3----4----5----6----7----8--> time
- jobs:
- a job: where is the start time, is the finish time, and is the value.
Produce a compatible schedule that has the maximum value.
Recursive solution
- Sort by finish time (asc).
- Find the optimal value in of first items:
- find largest such that .
- Opt($j$) = max(Opt($j-1$), Opt($i$) + $v_j$)
Proof of optimality
Using strong induction on .
Inductive hypothesis: Opt(0), ... , Opt($j$) is optimal.
Base cases or : There is only 1 possible optimal solution.
Inductive step:
- By IH, we have the optimal solution for and .
- The algorithm assures the dichotomy that the last interval is either in the solution or not.
- Take the max of the two dichotomies.
Time complexity: O($2^n$)
DP solution
Bellman equation
Pseudo code
Algorithm: WeightIntDP
Sort sigma by finish time
m[0] := 0
for j = 1 to n do
Find index i (linear search or binary search)
m[j] = max(m[j-1], m[i]+v_j)
Time complexity: O($n^2$) using linear search, O($n \log{n}$) using binary search.
Longest Increasing Subsequence
Problem definition
Given an integer array A[1.. ].
Find the longest increasing subsequence. That is, let be a sequence of indexes, we have A[ ] < A[ ] for all .
Definition of subsequence
I like watching the puddles gather rain
puddles: subsequenceI like watching the [puddles] gather rainlate train: subsequenceI [l]ike w[at]ching th[e] puddles ga[t]her [rain]
For an array of length n, there are subsequences.
Recursive solution
Algorithm: LIS
Input: Integer k and array of integers A[1..n].
Output: Return length of LIS where every value > k.
if n = 0 then return 0
else if A[1] <= k then
return LIS(k, A[2..n])
else
skip := LIS(k, A[2..n])
take := LIS(A[1], A[2..n]) + 1
return max{skip, take}
end
Find the length of the longest increasing subsequence by calling LIS(-Inf, A[1..n])
Time complexity: O($2^n$)
DP solution
Let L be a 2D array, where L[i, j] is the longest increasing subsequence of A[j..n] with every item > A[i], i<j.
Bellman equation
A[0] = $-\infty$
Populate from to 1; from 0 to or to 0.
Solution in
Time complexity: O($n^2$)
Coins in a line
Problem definition
Alice and Bob are playing a coin game. There are n (even) coins in a line. Each coin has a value. Starting with Alice, each player will take turns picking a coin from the head or the tail of the line. Both players try to play optimally in order to maximize the total value of their coins. Give an algorithm that outputs the maximum total value of coins that Alice can take.
Example
[3, 1, 6, 3]
A: 3; [1, 6, 3] //Alice takes 3 from the head
B: 3; [1, 6] //Bob takes 3 from the tail
A: 9; [1] //Alice takes 6 from the tail
B: 4; [] //Bob takes 1 from the head
//Alice wins
Dichotomy
The natural dichotomy of the problem is Alice picking a coin from the head or the tail of the line.
- Assume that Bob will play optimally
- For Alice's k-th turn:
- Coin array:
c[i..j], wherec[i]is the head andc[j]is the tail of the line. AliceOpt(c[i..j]) := max{ c[i] + BobOpt(c[i+1..j]), c[j] + BobOpt(c[i..j-1]) }
- Coin array:
- Bob wants to make a choice that minimizes Alice's total value of coins:
BobOpt(c[i..j]) := min{ AliceOpt(c[i+1..j]), AliceOpt(c[i..j-1]) }
DP solution
Let M be a 2D array, where M[i, j] is the maximum value possible for Alice when choosing from c[i..j], assuming Bob plays optimally.
Bellman equation
M[i, j] = max{ c[i] + min{ M[i+2, j], M[i+1, j-1]},
c[j] + min{ M[i+1, j-1], M[i, j-2]} }
M[i, i] = c[i]for alliM[i, j] = max{ c[i], c[j] }for alli = j-1- Populate
i' fromn-2to1;jfromnto3` - Solution:
M[1, n]
Time complexity: O($n^2$)
Max Subarray
Problem definition
Given an array A of integers, find the (non-empty) contiguous subarray of A of the maximum sum.
Dichotomy
An integer at i is either a part subarray started from an index j < i or an integer at i is a start of a new subarray.
DP solution
Finding the maximum sum
Let s be an array, where s[i] contains the value of the max subarray ending at i.
s[i] = max{ s[i-1] + A[i], A[i]) }
- Solution:
max{s}
Finding the subarray
Use another array that memoizes the starting index of the subarray ending at i.
start[i] = start[i-1] if s[i-1]+a[i] > a[] else i
Or trace back from the max value of s at index j until s[i] == A[i]
Time complexity: O($n$)
Subset Problem
Problem definition
Given a set of jobs each with a run time , we want to run these jobs in a single machine that we can use for time . What is the subset of jobs to run that maximizes ?
DP solution
Let be a 2D matrix, where is item indices from 0 to , and is a max weight from 0 to .
- for all and for all
- if and otherwise.
- Solution:
Time complexity: O($nW$)
- This not a polynomial runtime, but a pseudo-polynomial, because of which is unbounded.
Recovering the subset
Backtrace from from to and to until is 0. Trace down the first axis if or .
W=6, w1=2, w2=2, w3=3
v =[[0 0 0 0 0 0 0],
[0 0 2 2 2 2 2],
[0 0 2 2 4 4 4],
[0 0 2 3 4 5 5]]
//backtrace: w[3, 6]=5 => w[2, 3]=5-3=2 => w[2, 3]=2 => w[1, 3]=2 => w[0, 3]=2-2=0
//S = {w1, w3}
Knapsack Extension
Problem definition
You are a thief with a knapsack that can carry weight of goods. Given a set of items, each with a weight and a value . What is the subset of items to steal that maximizes with the constraint that ?
DP solution
Similar to the subset problem, but add instead of for the second case of the dichotomy.
- for all and for all
- if and otherwise.
- Solution:
Edit Distance Problem
Problem definition
Find the minimum number of the letter (insert, delete, replace) to change string A[1..m] to string B[1..n].
Ex: TUESDAY -> THUESDAY -> THURSDAY
This is equivalent to aligning the letters and counting mismatched letters.
Ex: T UESDAY
THURSDAY
DP solution
Let be a 2D matrix, where is the edit distance from A[1..i] and B[1..j].
Trichotomy
- Insertion:
- Deletion:
- Substitution:
- if , the cost of the substitution is 0, i.e., we don't need to do anything.
Bellman equation
- and
- Populate from 1 to , 1 to
- Solution:
Time complexity: O($mn$)
Shortest Path
Problem definition
Find the shortest path from s to each other node in a directed graph G=(V,E), where |V|=n and |E|=m. There are no cycles with negative weight.
DP solution
Let be a 2D matrix, where is the shortest path from to using .
- Solution:
Dichotomy
- Use edges
- Use edges
Bellman equation
- Solution:
- Recovery of actual path: An additional array that maintains the first hop from to .
Time complexity: O($mn$)