Day36| 1049.最后一块石头的重量II、494.目标和、474.一和零

2025-08-13

1049.最后一块石头的重量II

题目链接:1049.最后一块石头的重量II
文档讲解:代码随想录
状态:不会,不知道如何转化

思路

01背包衍生题目主要思路:在商品中取,使得容量有限的背包价值最大或取法数量、或元素数量最大等。

本题简单思路为将数组石头分成最相近两组(sum/2),此时做差最小。正确性就不证明了,囫囵吞枣吧,头受不了了。

此时的背包问题为:在容量为sum/2的背包中装填,石头的体积与价值相同(关键理解这是一个存在性+最优问题),则最终的dp[target]为最优。

题解

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0, target = 0;
        for(auto &i:stones)sum += i;
        target = sum/2;
        vector<int> dp(sum+1,0);
        for(int i = 0;i<stones.size();i++)
        {
            for(int j = target;j>=stones[i];j--)
            {
                dp[j] = max(dp[j],dp[j-stones[i]]+stones[i]);
            }
        }
        return sum-dp[target]-dp[target];//注意这个点,失误过很多次
    }
};

494.目标和

题目链接:494.目标和
文档讲解:代码随想录
状态:知道是背包问题,不知道怎么转化成次数

思路

01背包衍生题目主要思路:在商品中取,使得容量有限的背包价值最大或取法数量、或元素数量最大等。

本题知道了是找容量和为bagsize的组合数:此时的nums数组内容为所占体积,所求不是价值,递推公式需要进行修改。

对于组合数的递推公式类似于爬楼梯:①如果j<nums[i],此时放不下,不需要更改;②如果j>=nums[i],此时可以放下,需要增加新情况,注意不是赋值!!!dp[j] += dp[j - nums[i]]

题解

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for(auto &i:nums)sum += i;
        if((sum+target)%2!=0)return 0;
        if (abs(target) > sum) return 0; // 此时没有方案,因为不能是负数
        int bagsize = (sum+target)/2;
        vector<int> dp(bagsize+1,0);
        dp[0] = 1;//深刻理解
        for(int i = 0;i<nums.size();i++)
        {
            for(int j = bagsize;j>=nums[i];j--)
            {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[bagsize];
    }
};

474.一和零

题目链接:474.一和零
文档讲解:代码随想录
状态:彻底疯狂

思路

01背包衍生题目主要思路:在商品中取,使得容量有限的背包价值最大或取法数量、或元素数量最大等。

背包容量是mn多一个维度,但是做法一样,关键点在于所求值为背包内元素数量->仅仅把价值改为1即可。

还要注意本题本应是dp[i][j][k],简化为二维数组,遍历时由滚动性,顺序极其重要!!!

题解

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m+1,vector<int>(n+1,0));

        for(int i = 0;i<strs.size();i++)
        {
            int x = 0, y = 0;
            for(auto &i:strs[i]){if(i == '0')x++;else if(i == '1')y++;}
            for(int i = m;i>=x;i--)
            {
                for(int j = n;j>=y;j--)
                {
                    dp[i][j] = max(dp[i][j],dp[i-x][j-y]+1);
                }
            }
        } 
        return dp[m][n];  
    }
};

动态规划好似浑然天成,让我想破了脑子