【代码随想录】刷题Day43

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

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

其核心思路就是将一堆石头分为两堆,这两堆石头的重量尽可能相近,这样相互抵消得到的结果就是符合题目要求的。

那么这个问题就可以变成背包问题,我们拥有一个容量为石头质量总和一半的背包,那么只要知道这个背包最大能放入最多多重的石头堆即可。

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        int sum = 0;
        for(int i=0;i<stones.size();i++)
            sum+=stones[i];
        vector<int> dp(1501,0);
        for(int i=0;i<stones.size();i++)
        {
            for(int j=sum/2;j>=stones[i];j--)
            {
                dp[j]=max(dp[j],stones[i]+dp[j-stones[i]]);
            }
        }
        return sum-dp[sum/2]-dp[sum/2];
    }
};

2.目标和

494. 目标和

1.dp[j]:背包j容量所能达到要求的种类个数

2.dp[i]为i容量下的种类个数,其实有i种可能:当质量为1的物品放进去dp[i-1]有几种,当质量为2的物品放进去dp[i-2]有几种...当质量为i-1的物品放进去dp[1]有几种,这些情况相加。那么我们知道所谓的条件就是:dp[j] += dp[j - nums[i]];

3.初始化,dp[0]=1;因为dp[1]条件是dp[0]推出来的,如果dp[0]为0,后面都会变为0。

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        int sum = 0;
        for (int i = 0; i < nums.size(); i++)
            sum += nums[i];
        if ((sum + target) % 2 == 1 || sum < abs(target))
            return 0;
        int num = (sum + target) / 2;
        vector<int> dp(20001, 0);
        dp[0] = 1;
        for (int i = 0; i < nums.size(); i++)
        {
            for (int j = num; j >= nums[i]; j--)
            {
                dp[j] += dp[j - nums[i]];
            }
        }
        return dp[num];
    }
};

3.一和零

474. 一和零

1.由于想要根据 子集中 最多 有 m 个 0 和 n 个 1 来判断得到的子集最大数。那么我们能清楚所谓的背包容量由之前的一个维度,变为了两个维度。想要同时判断0和1的个数情况来求。所以dp数组也需要二维或者使用三维。

2.dp[i][j]:i个0,j个1的情况下,对应的最多子集是多少个。

3.循环,在以前的背包容量为一个维度时,循环有两层:物件和容量;现在的容量为两个维度,那么循环有三层:物件和两个容量。

4.dp条件为:面对一个string时,我们可以得到它对应的num0和num1,dp[i][j]数组在上一次的dp[i][j]和当前的dp[i-num0][j-num1]+1)中得到较大的值,dp[i][j]=max(dp[i][j],dp[i-num0][j-num1]+1);

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>>dp(m+1,vector<int>(n+1,0));
        for(auto e:strs)
        {
            int num0 = 0,num1 = 0;
            for(auto f:e)
            {
                if(f=='0')
                    num0++;
                else
                    num1++; 
            }
            for(int i=m;i>=num0;i--)
            {
                for(int j=n;j>=num1;j--)
                    dp[i][j]=max(dp[i][j],dp[i-num0][j-num1]+1);
            }
        }
        return dp[m][n];
    }
};

猜你喜欢

转载自blog.csdn.net/m0_63488627/article/details/130963513