Unbounded knapsack problem
Different from 0 -1 Knapsack problem, the unbounded knapsack problem allows using an unlimited number of instances of an item.
Let dp[i][v] represent the largest value we can get by choosing from the previous i items to put into a bag with a capacity of v, because we can take n instances of an item, the transition function can be written as
dp[i][v] = max{dp[i-1][v - k * c[i]] + k * w[i] | 0 <= k * c[i]<= v}
Template
Things to note:
Compared to 0-1 knapsack problem, the only difference is that we iterate v from 0 ( the reverse order of 0-1 knapsack problem)
The reason for this is that in 0 -1 knapsack problem, we have to make sure every item is only picked once. When considering whether or not to pick the ith item,we have our f[i][v] based on f[i-1][v-c[i]]. However, in an unbounded knapsack problem, because we can choose unlimited instances of the ith item, we have our f[i][v] based on f[i][v-c[i]].
for i=1..N
for v= cost..V
f[v]=max{f[v],f[v-cost]+weight}
Solution for 322
https://leetcode.com/problems/coin-change/
Note: Pay attention that this problem wants us to output the number of combinations. So there are slightly some differences.
- Initializing output[0] as 1.
- output[j] is the summation of output[j-c]
class Solution {
public int change(int amount, int[] coins) {
int[] output = new int[amount + 1];
output[0] = 1;
for(int c: coins){
for(int j = c; j < amount + 1; j++){
output[j] += output[j - c];
}
}
return output[amount];
}
}
Solution for 377
https://leetcode.com/problems/combination-sum-iv/
Things to note: different orders are viewed as different combinations
For example, we have 1, 2, 4
It‘s useful to write down some simple cases and then find the pattern
1 [1]
2 [1,1]、[2]
3 [1,1,1]、[2,1] 、[1,2]
4 [1,1,1,1]、[2,1,1]、[1,2,1]、[1,1,2]、[2,2]、[4]
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for(int i = 1; i <= target; i++){
for(int n : nums){
if(i >= n){
dp[i] += dp[i-n];
}
}
}
return dp[target];
}
}
Solution for 139
https://leetcode.com/problems/word-break/
class Solution {
public boolean wordBreak(String s, List<String> wordDict) {
boolean[] dp = new boolean[s.length() + 1];
dp[0] = true;
for(int i = 1; i <= s.length(); i++){
for(int j = 0; j < i; j++){
String splitted = s.substring(j,i);
if(wordDict.contains(splitted) && dp[j] == true ){
dp[i] = true;
break;
}
}
}
return dp[s.length()];
}
}