-
前言
状态:看完完全组合的解析之后,完成 518 和 377。CM70就是377。 -
更新
1 | 24-06-22 初始记录 |
初步题解
518 零钱兑换 II
题目链接:(https://leetcode.cn/problems/coin-change-ii/)
-
确定
dp[i]
的含义:填满 i(包括 i)这么大容积的包,有dp[i]
种方法 -
递推公式:
dp[i] += dp[i - coin]
。 -
dp 数组的初始化:
dp[0] = 1
。假设数组个数为 0,获取 dp[0],就是 1。 -
遍历顺序:从前向后遍历。
-
打印 dp 数组(用于 debug)
1 | /** |
377 组合总和 Ⅳ
题目链接:(https://leetcode.cn/problems/combination-sum-iv)
如果求组合数就是外层 for 循环遍历物品,内层 for 遍历背包。
如果求排列数就是外层 for 遍历背包,内层 for 循环遍历物品。
1 | /** |
70 爬楼梯 (进阶)
题目链接:(https://kamacoder.com/problempage.php?pid=1067)
就是完全背包 + 排列,解法和上题一模一样。nums 取值为 1- 每次最多爬的阶梯数量
看解析
完全背包
有 N 件物品和一个最多能背重量为 W 的背包。第 i 件物品的重量是 weight[i]
,得到的价值是 value[i]
。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。
完全背包和 01 背包问题唯一不同的地方就是,每种物品有无限件。
二维数组:
-
递推公式:
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - item[i][0]] + item[i][1])
(即,不重复存放当前物品/重复存放当前物品) -
dp 数组的初始化:
dp[i][0]
均为 0。dp[0][j]
为第一格按背包大小取重复值。 -
遍历顺序:从前向后遍历。
1 | public static void main(String[] args) { |
一维数组(状态压缩):
-
递推公式:
dp[i] = Math.max(dp[i], dp[i - item[0]] + item[1]);
-
dp 数组的初始化:
dp[0] = 0
-
遍历顺序:从前向后遍历。(而完全背包的物品是可以添加多次的,所以要从小到大去遍历。(😅老实说,看了好几几遍都没懂))
-
这里完全背包一维 dp 数组可以交换遍历顺序:因为
dp[j]
是用到其左边的数据dp[j - weight[i]]
的,而先遍历背包再遍历物品也是满足的。
1 | public static void integerBreak1(int n, int[][] items) { |
518 零钱兑换 II
解析:(https://programmercarl.com/0518.零钱兑换II.html)
377 组合总和 Ⅳ
解析:(https://programmercarl.com/0377.组合总和Ⅳ.html)