代码随想录算法训练营第三十五天 | 416.分割等和子集
416. 分割等和子集
题目链接:416. 分割等和子集 - 力扣(LeetCode)
文章讲解:代码随想录
视频讲解:动态规划之背包问题,这个包能装满吗?| LeetCode:416.分割等和子集_哔哩哔哩_bilibili
思路:
1. 确定dp数组以及下标的含义
01背包中,dp[j] 表示: 容量(所能装的重量)为j的背包,所背的物品价值最大可以为dp[j]。
如果背包所载重量为target, dp[target]就是装满 背包之后的总价值,本题中每一个元素的数值既是重量,也是价值,当 dp[target] == target 的时候,背包就装满了。
2. 确定递推公式
01背包的递推公式为:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
相当于背包里放入数值,那么物品i的重量是nums[i],其价值也是nums[i]。
所以递推公式:dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
去掉物品i容量的最大价值+物品i的价值就是当前i容量的最大价值
(相当于背包问题二维变一维去掉前面的i,下面是背包问题二维写法)
不放物品i:背包容量为j,里面不放物品i的最大价值是dp[i - 1][j]。
放物品i:背包空出物品i的容量后,背包容量为j - weight[i],dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]且不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值
递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
3. dp数组如何初始化
在01背包,一维dp如何初始化,已经讲过,
从dp[j]的定义来看,首先dp[0]一定是0。
4.确定遍历顺序
因为从左上角和正上找数,倒序就不会覆盖之前的值,因为推导只用到左上和上边的数据,所以要从最右边遍历
5.举例推导dp数组