LeetCode动态规划经典题目(九):0-1背包问题

学习目标:

0-1背包问题


学习内容:

9. LeetCode416. 分割等和子集icon-default.png?t=MBR7https://leetcode.cn/problems/partition-equal-subset-sum/

10. LeetCode1049. 最后一块石头的重量 IIicon-default.png?t=MBR7https://leetcode.cn/problems/last-stone-weight-ii/


学习产出:

独立解决以上题目,并懂得举一反三。

目录

8. 背包问题

9. LeetCode416. 分割等和子集

10. LeetCode1049. 最后一块石头的重量 II


8. 背包问题

0-1背包:
有n件物品和一个最多能背重量为w 的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

思路:
1.动态规划二维表:
dp[i][j]:任意取0~i的物品,放假容量为j的背包里,价值总和最大值。
2.转移方程:
对于物品i:
  2.1取物品i:dp[i][j]=dp[i-1][j](其实是背包当前容量无法再放入物品i)
  2.2不取物品i:dp[i][j]=dp[i-1][j-weight[i]]+value[i](j-weight[i]是为物品i腾出空间)
综上:dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i])
3.初始化dp:
由转移方程可知,新dp值由左上角推得,所以先初始化第0行和第0列

完整代码:
int maxValueInBag(vectorweight,vectorvalue,int capacity){
    //dp[i][j]:任意取0~i的物品,放假容量为j的背包里,价值总和最大值。
    vector>dp(weight.size(),vector(capacity+1));
    
    //初始化dp
    for(int i=0;iweight,vectorvalue,int capacity){
    vectordp(capacity+1);
    //初始化dp
    for(int j=weight[0];j<=capacity;j++){
        dp[j]=value[0];
    }
    for(int i=1;i=weight[i];j--){//因为依赖左上角值,所以从右往左遍历
            //如果当前j

9. LeetCode416. 分割等和子集

思路:
转换成0-1背包问题,只要dp中有值等于sum/2的,就return true

1. dp[i][j]:从0~i下标中组合起来的值不超过j的最大值
2. dp[i][j]=max(dp[i-1][j],dp[i-1][j-nums[i]]+nums[i])
3. 初始化dp
    
class Solution {
public:
    bool canPartition(vector& nums) {
        int sum=0;//nums总和
        for(int i=0;i>dp(nums.size(),vector((sum/2)+1));
        
        //初始化dp
        for(int i=0;i& nums) {
        int sum=0;//nums总和
        for(int i=0;idp((sum/2)+1);
        for(int j=nums[0];j<=sum/2;j++){
            dp[j]=nums[0];
        }
        for(int i=1;i=nums[i];j--){
                dp[j]=max(dp[j],dp[j-nums[i]]+nums[i]);
            }
        }
        return dp[sum/2]==sum/2;
    }
};

10. LeetCode1049. 最后一块石头的重量 II

思路:
可把问题转变成将石头分成两堆且质量和尽可能相同,即靠近sum/2,这样两堆石头互相磨损完后,剩余石头质量最小。

1. dp[i][j]:从0~i的石头中,取最靠近质量j的石头组合的质量和
2. dp[i][j]=max(dp[i-1][j],dp[i-1][j-stones[i]]+stones[i])
3. 初始化dp

class Solution {
public:
    int lastStoneWeightII(vector& stones) {
        int sum=0;
        for(int i=0;i>dp(stones.size(),vector(target+1));

        //初始化dp
        for(int i=0;i& stones) {
        int sum=0;
        for(int i=0;idp(target+1);
        for(int j=stones[0];j<=target;j++){
            dp[j]=stones[0];
        }

        for(int i=1;i=stones[i];j--){
                dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return abs((sum-dp[target])-dp[target]);
    }
};

你可能感兴趣的:(leetcode,动态规划,c++,算法,数据结构)