重庆网站建设快速建站,大连网站建设介绍,ae射频电源成色,wordpress 页面文件今天只有1道题#xff0c;属于动态规划的01背包问题的应用。首先理解一下动态规划的01背包问题。推荐一个视频#xff0c;动态规划DP0-1背包#xff0c;这是我认为讲得最为通透的。很多讲解动态背包问题的#xff0c;一上来就画二维表格#xff0c;遍历背包或者遍历容量属于动态规划的01背包问题的应用。首先理解一下动态规划的01背包问题。推荐一个视频动态规划DP0-1背包这是我认为讲得最为通透的。很多讲解动态背包问题的一上来就画二维表格遍历背包或者遍历容量其实本质上根本就看不懂那个二维表格是什么意思为什么容量每次都要从0开始遍历。从原理上讲容量从0开始只是一种假设为的是让后面的背包如果装东西了那么背包容量就会减少再减少了容量后怎么挑选物品才会使得质量最高因此需要从0遍历这些都是起了给后面的递归初始化一个值的作用。 小偷偷东西有一个8容量背包那么他开始从编号4开始偷也可以从编号1开始偷他有两种选择偷或者不偷。如果偷那么它的背包剩余容量就是8 - 5 3同时产生价值8如果不偷则背包容量为8产生价值为0接着开始偷第二件物品也就是编号3又是一个选择偷与不偷的过程。最后就会生成一棵二叉树每个叶子节点都是不同选择下的结果选择最大的叶子节点就是得到最大的价值。 因此就会产生一个状态转移方程这个状态转移方程就是一种决策如果背包容量不够也就是物品太重那么它产生的价值就是上次物品决策时的价值也就是fk - 1,w同时剩余容量为w也就背包的容量没有改变。如果背包容量足够那么他就面临两种选择偷和不偷如果不偷产生的价值不变容量不变如果偷那么它的总价值就加上这个物品的价值同时背包容量就相应减少。这时可以看到背包容量减少后对应的一个小背包容量面临的选择是剩下两个物品的决策。这时对应的背包容量和剩下物品中对应获取的最大值在前面的遍历已经有给出了所以查表就可以得到对应的最大值也就是这种决策下的产生的最大价值。
其实在引申下去就是从只有1个物品和只有有限背包容量时能产生的最大价值。接着有两个物品和有限背包容量时的选择选择第2个物品后就回头看剩下的背包容量以及只有1个物品时对应的价值返回不选择第二件物品和选择了第二件物品的价值的最大值。也就是状态转移方程中的第wk w的情况。 最终的f4,8就是我们决策的结果其余的表格数字只是一个铺垫都是每个决策产生的最大值但是最后的f4,8才是我们有4个物品同时背包容量为8的结果。所以里面的关系要搞清楚表格的其他数字都和我们01背包的题目没有关系但是它是一个重要的推导过程他有点类似于遍历所有结果把决策的结果反应在表格上。可能我讲得确实不够清楚但是强烈推荐看视频讲解从原理上解剖背包问题和决策真的可以深刻理解这个表格以及整个动态规划的核心。动态规划DP0-1背包。
力扣题目416. 分割等和子集
给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集使得两个子集的元素和相等。
示例 1
输入nums [1,5,11,5]
输出true
解释数组可以分割成 [1, 5, 5] 和 [11] 。
示例 2
输入nums [1,2,3,5]
输出false
解释数组不能分割成两个元素和相等的子集。提示
1 nums.length 2001 nums[i] 100回到题目分割等和子集这个可以看成背包容量为整个集合的和的一半只要背包正好装满那么这个背包的价值就是整个集合的一半背包的和与剩下的子集的和相等可以返回true。因此在借用这个思想遍历所有物品也就是集合里面的元素从只有1个元素可以选择到所有的元素都可以选择在这个过程中只要找到背包满的情况就能输出true因为只要选择了这些元素就可以了。
class Solution {public boolean canPartition(int[] nums) {int sum 0;for(int num : nums){sum num;}if(sum % 2 1 || nums.length 1){return false;}int[][] dp new int[nums.length][sum / 2 1];for(int i 0; i nums.length; i){dp[i][0] 0;}for(int j 0; j sum / 2; j){if(j nums[0]){dp[0][j] nums[0];}}for(int i 1; i nums.length; i){for(int j 1; j sum / 2; j){if(j nums[i]){dp[i][j] Math.max(dp[i - 1][j] ,dp[i - 1][j - nums[i]] nums[i]);}else{dp[i][j] dp[i - 1][j];}}//这一步是关键因为不知道选多少个元素所以每次添加一个元素进行选择时就判断一次//正好满足条件就可以返回true否则就再加一个元素直到加到没有元素可以加后结束遍历返回falseif(dp[i][sum / 2] sum / 2){return true;}}// for (int i 0; i nums.length; i) {// for (int j 0; j sum / 2; j) {// System.out.print(dp[i][j] );// }// System.out.println();// }return false;}}
终于把01背包吃下了不容易呀