DynamicProgrammingNotes
DynamicProgrammingNotes
LECTURE
1.) Top-Down : Start solving the given problem by breaking it down. If you
see that the problem has been solved already, then just return the saved
answer. If it has not been solved, solve it and save the answer. This is
usually easy to think of and very intuitive. This is referred to as
Memoization. (We will go from higher states towards lower states).
2.) Bottom-Up : Analyze the problem and see the order in which the
sub-problems are solved and start solving from the trivial subproblem, up
towards the given problem. In this process, it is guaranteed that the
subproblems are solved before solving the problem. This is the Iterative
Approach. (We will go from lower states towards higher states).
Types of problems that can be solved using Dp/Motivation
behind studying the topic :
int fibo_simple(int x) {
if (x <= 2)return 1;
return fibo_simple(x - 1) + fibo_simple(x - 2);
}
int fibo_with_memo(int x) {
if (x <= 2) {
dp[x] = 1;
}
else {
dp[x] = fibo_with_memo(x - 1) +
fibo_with_memo(x - 2);
}
return dp[x];
}
int n;
cin>>n;
int fibo[n+1];
fibo[1] = 1, fibo[2] = 1;
for (int i = 3; i<= n; i++) {
fibo[i] = fibo[i - 1] + fibo[i - 2];
}
In the above case, fibo[i] denotes the i’th term of the fibonacci series
which seems very trivial and obvious but it is not always the case.
2 cases :
[…………] 0
.…………...1
[………] 01
Hence we get the relation :
● 0-1 Knapsack
● Longest Increasing Sequence (LIS)
● Coin change Problem
● Longest common subsequence (LCS)
● LIS (in nlogn)
● Solving recursive relations for large n (order of
1e9,1e18) using matrix exponentiation
Example-
N=7
A=[2,1,8,5,3,6,9]
1,3,6,9
Ans=4
Solution :
Let dp[i] denote the length of Longest Increasing Subsequence ending
at i.
Then for every i in 1 to n,we see every j from 1 to i-1. If arr[i]>arr[j],
then arr[i] is a possible contender for the last element of the LIS and
we can include arr[i] in the LIS ending at j. We take the maximum of
all the values of dp[i] to get the answer.(This is because LIS can end at
any index and not necessarily n)
}
cout<<ans;
https://www.geeksforgeeks.org/longest-monotonically-increasing-subs
equence-size-n-log-n/
Practice Task -
https://codeforces.com/problemset/problem/269/B
(Try to implement in NlogN as well)
Extra Task-
Problem: There are N items ,each of them having some weight w[i]
and value v[i] associated with them.You also have a knapsack with
capacity S.
You need to put a subset of items in the Knapsack such that their total
weight
does not exceed S and their total value is Maximized.
You cannot break an item i.e either pick it completely or don’t pick it.
(Hence the name 0-1 Knapsack).
A 5 4 0.8
B 4 3 0.6
C 4 2 0.5
Knapsack capacity,S = 8.
What if you just need to tell what is the maximum weight <=S that you can
achieve by choosing a subset of the items.
Example:
item weight
A 1
B 3
Total 0 1 2 3 4
Weight
{} 1 0 0 0 0
{1} 1 1 0 0 0
{1,3} 1 1 0 1 1
In the end, simply report the maximum ‘x’ <=S such that, dp[n][x] =1.
int n, S;
bool dp[n+1][S+1];
memset(dp,0,sizeof(dp));
int w[n+1];
Let dp[i][j] denote the maximum value that we can get from first ‘i’
items and for a total weight ‘j’.
int n, S;
dp[0][0] = 0;
if (j >= w[i]) {
dp[i][j] = max(dp[i][j], dp[i - 1][j - w[i]] + v[i]);
}
}
}
int answer = 0;
Solution : Let f[i][j] denote the no. of ways to get sum j using first i
coins only.
Sum 0 1 2 3 4 5 6 7 8 9 10
{} 1 0 0 0 0 0 0 0 0 0 0
{1} 1 1 1 1 1 1 1 1 1 1 1
{1,2} 1 1 2 2 3 3 4 4 5 5 6
{1,2,5} 1 1 2 2 3 4 5 6 7 8 10
Reason: for v[i] =x , f[i][j] takes “some” time to compute and there
are total n*m states.
Where x= V[i]
HW PROBLEM:
Example -
45
KXBY
ACXCY
Answer =2
(XY)
Solution:
Code:
cin >> n >> m;
cin>>s1>>s2;
int dp[n+1][m+1];
//dp[i][j] denotes length of Longest Common Subsequence
//when we consider first i characters of s1 and j characters
//of s2
for(i=0;i<=n;i++)
{
for(j=0;j<=m;j++)
{
if((i==0)||(j==0))
{
dp[i][j]=0;
}
else
{
if(s1[i-1]==s2[j-1])
dp[i][j]=1+dp[i-1][j-1];
else
{
dp[i][j]=std::max(dp[i-1][j],dp[i][j-1]);
}
}
}
}
int ans=dp[n][m];
cout<<ans;
Practice Task :
https://cses.fi/problemset/task/1639
Extra Task:
Try to print the LCS of 2 strings.
Resources:
1) Intuition Behind Dp
2) Knapsack
3) Coin Change
4) LIS/LCS
5) LIS in nlogn
6) BitMask Dp
7) Matrix Exponentiation
8) Longest Common Subsequence (Visualisation)