Day43 动态规划 LeetCode 1049 494 474

58 阅读2分钟

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

心得

  • 完全不会,想的是排列,复杂度过高

题解

  • 将问题转化为分两堆,尽可能同,这样两堆作差就最小,转成0 1背包问题,跟拆分整数一致,此题重量和价值都是一样
class Solution {
public:
    int lastStoneWeightII(vector<int>& stones) {
        vector<int> dp(1501, 0); // dp[j] 容量为j的背包可以背的最大重量
        int sum = 0;
        for (int stone : stones) {
            sum += stone;
        }
        for (int i = 0; i < stones.size(); i++) {// 物品
            for (int j = sum / 2; j >= stones[i]; j--) {
                dp[j] = max(dp[j], dp[j - stones[i]] + stones[i]);
            }

        }
        return sum - dp[sum / 2] - dp[sum / 2]; // sum / 2向下取整
        
    }
};

494. 目标和

心得

  • 完全不会

题解

  • 还是一个转换的问题,选择的时候,有正有负,目标和target,也就是说正的一堆,负的另一堆,即left - right = target, left + right = target,求和消right得left = (target + sum) / 2这样就转化为遍历,背包容量为left的情况
  • 但是本题在于并非求价值最大,而是恰好,也就是之前的递推公式max是每次取得最大,这是其实取得就是每次的和,也就是+=
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 (abs(target) > sum) return 0; // 不存在方案
        if ((target + sum) % 2 == 1) return 0; // 也存在方案
        int bagSize = (target + sum) / 2;
        vector<int> dp(bagSize + 1, 0); // dp[j] 容量为j,
        dp[0] = 1; // 此处不同于一般的0初始化,递推公式后面的都是基于此
        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. 一和零

心得

  • 完全不会

题解

  • 还是01背包,主要还是取不取的问题,然后取时候有约束使得取最值,这种最值情况就是原01背包递推公式直接套用,但是约束条件扩充为二维,逻辑还是与之前的一致,逆序,对于max类型的初始化同样都是0
class Solution {
public:
    int findMaxForm(vector<string>& strs, int m, int n) {
        vector<vector<int>> dp(m + 1, vector<int>(n + 1, 0)); // m个1 n个0 dp[m][m]个数
        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];
    }
};