常见的背包问题有1、组合问题。2、True、False问题。3、最大最小问题。
1、组合问题:
377. 组合总和 Ⅳ
494. 目标和
518. 零钱兑换 II
2、True、False问题:
139. 单词拆分
416. 分割等和子集
3、最大最小问题:
474. 一和零
322. 零钱兑换
1. 组合问题公式
dp[i] += dp[i-num]
2. True、False问题公式
dp[i] = dp[i] or dp[i-num]
3. 最大最小问题公式
dp[i] = min(dp[i], dp[i-num]+1)或者
dp[i] = max(dp[i], dp[i-num]+1)
以上三组公式是解决对应问题的核心公式。
当然拿到问题后,需要做到以下几个步骤:
1.分析是否为背包问题。
2.是以上三种背包问题中的哪一种。
3.是0-1背包问题还是完全背包问题。也就是题目给的nums数组中的元素是否可以重复使用。
4.求组合数 还是 排列数
- 如果求组合数就是外层for循环遍历物品,内层for遍历背包。如 518. 零钱兑换 II
- 如果求排列数就是外层for遍历背包,内层for循环遍历物品。如 377. 组合总和 Ⅳ
主要的模板转载自 这位大佬,为了方便以后查看,我把部分截图过来
01背包
二维写法
一维写法
01背包一维写法中 内部循环必须倒序的原因
因为二维压缩到一维的根本原理是,dp[j] 和 dp[j-nums[i-1]] 还没被新结果覆盖的时候,相当于二维 dp 中的 dp[i-1][j] 和 dp[i-1][j-nums[i-1]]。
那么,我们就要做到:在计算新的 dp[j] 的时候,dp[j] 和 dp[j-nums[i-1]] 还是上一轮外层 for 循环的结果。
如果你从前往后遍历一维 dp 数组,dp[j] 显然是没问题的,但是 dp[j-nums[i-1]] 已经不是上一轮外层 for 循环的结果了,这里就会使用错误的状态,当然得不到正确的答案。
完全背包
二维写法
一维写法
完全背包一维写法中 内部循环必须正序的原因
这样可以使得一个物品可以取多次,符合完全背包要求。
完全背包 练习题