#完全背包
首先0-1 背包和完全背包的区别是,0-1 背包每个物品只能装一次,完全背包的物品可以装多次。0-1 背包为了不重复使用,会选择倒序便利,且是先遍历物品再遍历背包。完全背包问题一般是正序遍历,因为同一个物品可以用多次,且遍历顺序可以颠倒。
#LeetCode518. Coin Change II
#LeetCode518. 视频讲解:动态规划之完全背包,装满背包有多少种方法?组合与排列有讲究!| LeetCode:518.零钱兑换II_哔哩哔哩_bilibili
本题求的是组合数并不是排列,组合数是不强调元素的顺序的,所以[2, 2, 1] 和[2, 1, 2] 是相同的。
动态规划五部曲:
1. 确定dp[j] 的含义,在这里dp[j] 代表重量为j 的背包,装满共有dp[j] 种方法
2. 递推公式,dp[j] = dp[j - coins[i]]
3. dp数组应该如何初始化,dp[0] = 1, 是为了避免在递推的过程中无意义,其余初始化为0
4. 遍历顺序,是从前向后
5. 打印dp 数组,可以帮助检查
代码:
class Solution {
public int change(int amount, int[] coins) {
int[] dp = new int[amount + 1];
dp[0] = 1;
for (int i = 0; i < coins.length; i ++) {
for (int j = coins[i]; j <= amount; j++) {
dp[j] += dp[j - coins[i]];
}
}
return dp[amount];
}
}
#LeetCode377. Combination Sum IV
#LeetCode377. 视频讲解:动态规划之完全背包,装满背包有几种方法?求排列数?| LeetCode:377.组合总和IV_哔哩哔哩_bilibili
与零钱交换的题目相似,但是这个是排列,不是组合,[1, 2, 1] 和[1, 1, 2]是不同的组合。
在纯完全背包类问题中,求装满这个背包的最大价值或者是否能装满,两个for 循环是可以颠倒的,如果问装满背包需要几个方法,那么需要考虑排列还是组合(是否有顺序问题)。
比如:有n 个台阶,一次可以1 ~ m步,那么n 个台阶类似背包的容量,1 ~ m 步是物品。
代码:
class Solution {
public int combinationSum4(int[] nums, int target) {
int[] dp = new int[target + 1];
dp[0] = 1;
for (int i = 0; i <= target; i++) { // bag
for (int j = 0; j < nums.length; j++) { // item
if (i >= nums[j]) {
dp[i] += dp[i - nums[j]];
}
}
}
return dp[target];
}
}