• 随想录一刷Day43——动态规划


    Day43_动态规划

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

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

    要让最后剩下的石头的重量最小,即消磨得石头的重量越多,即让重量尽可能接近的石头两两相碰。于是可以统计石头的总重量sum,将问题转化为,在容量为sum/2的背包中放入尽可能重的石头,这样背包中的石头与没有装入背包的石头互相碰撞,最后一定能消磨到只剩 sum - dp[target] - dp[target] 的重量。
    粗糙证明一下结论正确性,如果没有将背包中装入最大的重量,一定有石头本可以装入背包而没有装入背包,那么消磨掉背包中的石头后,没有装入背包的石头还需要彼此消磨,直到把本可以装进去却没装进去的部分消磨掉,相当于装进了背包,所以上述方法是正确的。

    class Solution {
    public:
        int lastStoneWeightII(vector<int>& stones) {
            int stones_size = stones.size();
            int sum = 0;
            for (int i = 0; i < stones_size; ++i) sum += stones[i];
            int target = sum / 2;
            vector<int> dp(target + 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];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    15. 目标和

    494. 目标和
    思路:

    1. dp[j] 表示填满容量 j 的种类数
    2. d p [ j ] = ∑ d p [ j − n u m s [ i ] ] dp[j] = \sum{dp[j - nums[i]]} dp[j]=dp[jnums[i]]
    3. 初始化 dp[0] = 1 ,填满容量 0 的方法数有一种,就是不填
    4. 外层循环遍历整个nums[]数组,内层循环倒序遍历背包容量,因为扩展到二维用的是上一行的处理结果,从前往后的话会更新前面的结果,导致后面的计算出错。

    nums中正数相加的和为 positive_sum
    则有 positive - (sum - positive) = target
    将问题转化为求整数之和为 positive_sum = (sum + target) / 2 的方法数,使用 01 背包,求容量为 positive_sum 的背包被装满的方法数

    class Solution {
    public:
        int findTargetSumWays(vector<int>& nums, int target) {
            int nums_size = nums.size();
            int sum = 0;
            for (int i = 0; i < nums_size; ++i) sum += nums[i];
            if (abs(target) > sum) return 0;
            if ((sum + target) & 1) return 0; // positive - (sum - positive) = target
            int positive_sum = (target + sum) / 2; // 
            vector<int> dp(positive_sum + 1, 0);
            dp[0] = 1; // 初始化
            for (int i = 0; i < nums_size; ++i) {
                for (int j = positive_sum; j >= nums[i]; j--) {
                    dp[j] += dp[j - nums[i]];
                }
            }
            return dp[positive_sum];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    17. 一和零

    474. 一和零
    思路:

    经典 01 背包,只不过容量分两维,0的容量一维,1的容量一维。每个字符串带来的价值是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 (string str : strs) {
                int ZeroNum = 0, OneNum = 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];
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
  • 相关阅读:
    FFmpeg5.1.3编译动态库详细教程(基于Linux虚拟机)
    matlab习题 —— 程序控制流程练习
    20221106
    【LeetCode贪心#09】用最少数量的箭引爆气球,无重叠区间,合并区间(涉及区间重叠情况判断与处理)
    Vue页面内容未保存时离开页面做弹框提示
    Dubbo Gateway - 网关设计
    Python tkinter - 第10章 文本控件(Text)属性
    java高校自习室座位预订系统springboot+vue
    【归并排序/快排/堆排序】912. 排序数组
    SkyWalking安装部署
  • 原文地址:https://blog.csdn.net/zhiai_/article/details/127644874