代码随想录算法训练营day35

5 阅读2分钟

1049 最后一块石头的重量II 这道题和之前的分割子集问题没有特别大区别,有两个特殊的地方是如何处理返回值,返回值设计是sum-2*dp[target]。重点还是需要对的动态规划的思路进行掌握

class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        //将本题简化为分割子集的01背包问题
        //剪支处理
        if(stones.size()==0) return 0;
        if(stones.size()==1) return stones[0];
        //设计dp数组
        vector<int> dp(15001,0);//最多只有30块石头,每块石头最多100
        //dp[i]指代背包内此时装载的物品重量,i指代此时背包的容量
        //题设即求是否可以将石头分割成1/2 重量
        int sum=0;
        for(int i=0;i<stones.size();i++){
            sum+=stones[i];
        } 
        int target=sum/2;//确定target为sum的一半
        //执行递推公式
        for(int i=0;i<stones.size();i++)//从石头开始遍历
           for(int j=target;j>=stones[i];j--){//从大至小开始对背包容量,对大于stones[i]的情况进行剪支处理
               dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);//当背包容量比石头重量大时,比较装入较重石头
           }
        //返回结果
        return sum-2*dp[target];
    }
};

494.目标和


class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int target) {
        //区分特殊情况,题设nums.size()>=1
        int sum=0;//使用sum记录nums之和
        for(int i=0;i<nums.size();i++){
            sum+=nums[i];
        }
        if(abs(target)>sum) return 0;//target的绝对值比和大
        if ((target + sum) % 2 == 1) return 0; // 此时没有方案
        int bagSize = (target + sum) / 2;//目标重量
        //设计dp数组
        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 一和零,这道题的关键点在于弄清楚是有两个背包,0背包和1背包,物品时数组里的数字,但是装1的是一个背包,装0的是一个背包,这两个背包条件需要并行满足

class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int> (n + 1, 0)); // 默认初始化0
        for (string str : strs) { // 遍历物品
            int oneNum = 0, zeroNum = 0;
            for (char c : str) {
                if (c == '0') zeroNum++;
                else oneNum++;
            }
            for (int i = m; i >= zeroNum; i--) { // 遍历背包容量且从后向前遍历!
                for (int j = n; j >= oneNum; j--) {
                    dp[i][j] = max(dp[i][j], dp[i - zeroNum][j - oneNum] + 1);
                }
            }
        }
        return dp[m][n];
    }
};