• day-43 代码随想录算法训练营(19) 动态规划 part 05


    1049.最后一块石头的重量||(有点感觉了)

    分析:
    • 只有石头不相等时,才会剩下石头,所以相等的部分会两两抵消;
    • 所以最后一块石头一定是两两抵消的结果,总和-抵消*2=最后一块石头
    • 转换为背包问题:容量=总和/2 看最多能装多少,装满即完全抵消
    思路:
    • 1.dp存储:当容量为j时,装的最大重量dp[j]
    • 2.dp [ j ] =max(dp [ j ],dp [ j - stones [ i ] ] + stones [ i ] ) 
    • 3.初始化:全为0
    • 4.遍历顺序:外层遍历石头,内层遍历背包容量
    1. class Solution {
    2. public:
    3. int lastStoneWeightII(vector<int>& stones) {
    4. int total=0;
    5. for(auto it:stones) total+=it;
    6. int target=total/2;
    7. vector<int>dp(total+1,0);
    8. for(int i=0;isize();++i){
    9. for(int j=target;j>=stones[i];--j){
    10. dp[j]=max(dp[j],dp[j-stones[i]]+stones[i]);
    11. }
    12. }
    13. return total-2*dp[target];
    14. }
    15. };

    494.目标和

    分析:
    • 正数值add  负数值sub  总和sum
    • add-sub=target -> add-(sum-add)=target -> add=(target+sum)/2
    • 得出需要达到的正数值,转换为背包问题:装满add有几种方法
    思路:
    • 1.dp存储:值为 j 时有dop[j]种方法装满
    • 2.dp[j]+=dp[j-nums[i]]  只要装入nums[i]刚好装满的方法都可行
    • 3.初始化:dp[0]=1 不装就是一种方法
    • 4.遍历顺序:外层遍历元素  内层遍历背包容量
    1. class Solution {
    2. public:
    3. int findTargetSumWays(vector<int>& nums, int target) {
    4. int total=0;
    5. for(auto it:nums) total+=it;
    6. if(abs(target)>total) return 0;
    7. if((target+total)%2==1) return 0;//如果为奇数,说明add无法取整,无法得出结果
    8. int add=(target+total)/2;
    9. vector<int>dp(add+1,0);
    10. dp[0]=1;
    11. for(int i=0;isize();i++){
    12. for(int j=add;j>=nums[i];--j){
    13. dp[j]+=dp[j-nums[i]];
    14. }
    15. }
    16. return dp[add];
    17. }
    18. };

    474.一和零

    分析:
    • 分析:在满足0和1个数的同时,尽量多的装字符串
    • 转化为背包问题:二维容量:zeroNum oneNum 的容量下,最多能装多少物品
    思路:
    • 1.dp存储:当可以装0为i个,1为j个时,最多可以装dp[i][j]个字符串
    • 2.dp[i][j]=max(dp[i][j],dp[i-zeroNum][j-oneNum]+1);  装入当前值后,总数+1
    • 3.初始化:全为0
    • 4.遍历顺序:外层遍历字符串数组,内层两个for循环进行字符容量遍历
    1. class Solution {
    2. public:
    3. int findMaxForm(vector& strs, int m, int n) {
    4. vectorint>>dp(m+1,vector<int>(n+1,0));
    5. for(int i=0;isize();i++){
    6. int oneNum=0,zeroNum=0;
    7. for(char it:strs[i]){//记录当前字符0和1的数量
    8. if(it=='0') zeroNum++;
    9. else oneNum++;
    10. }
    11. for(int j=m;j>=zeroNum;--j){//二维装填
    12. for(int k=n;k>=oneNum;--k){
    13. dp[j][k]=max(dp[j][k],dp[j-zeroNum][k-oneNum]+1);
    14. }
    15. }
    16. }
    17. return dp[m][n];
    18. }
    19. };

    518.零钱兑换 ||(坐牢)

    分析:完全背包
    思路:
    • 1.dp存储:价值 j 时,可以装的方法有 dp[j] 种
    • 2.dp[j]+=dp[j-coins[i]]
    • 3.初始化:dp[0]=1
    • 4.遍历顺序:外层遍历硬币,内层遍历容量
    1. class Solution {
    2. public:
    3. int change(int amount, vector<int>& coins) {
    4. int n=coins.size();
    5. vector<int>dp(amount+1);
    6. dp[0]=1;
    7. for(int i=0;i
    8. for(int j=coins[i];j<=amount;j++){
    9. cout<
    10. dp[j]+=dp[j-coins[i]];
    11. }
    12. }
    13. return dp[amount];
    14. }
    15. };

    377.组合总和IV(微微坐牢啊)

    思路:
    • 1.dp存储:和为 j 时,组成这个和的种数为 dp[j]
    • 2.dp[j]+=dp[j-nums[i]];
    • 3.初始化:dp[0]=1
    • 4.遍历顺序:外层遍历容量  内层遍历元素

    本题需要的是排列:所以先遍历容量(背包)

    1. class Solution {
    2. public:
    3. int combinationSum4(vector<int>& nums, int target) {
    4. vector<int>dp(target+1,0);
    5. dp[0]=1;
    6. for(int i=0;i<=target;i++){
    7. for(int j=0;jsize();j++){
    8. if(i-nums[j]>=0 && dp[i]<=INT_MAX-dp[i-nums[j]])
    9. dp[i]+=dp[i-nums[j]];
    10. }
    11. }
    12. return dp[target];
    13. }
    14. };

  • 相关阅读:
    LeetCode | 19. 删除链表的倒数第 N 个结点
    数据采集中的基本参数
    【Svelte】-(4)If 条件判断语句 / Each 循环语句 / Await 异步处理块
    python绘图技巧(高清图)
    振弦采集仪和传感器形成完整链条的岩土工程解决方案
    故障:不能打开 Office 应用程序,并指示有账户正在登录
    开源贴片机OpenPnp使用体验
    【基础理论】柯西分布
    VsCode中设置文本格式化(超详细)
    QT的安装 [新版2022]
  • 原文地址:https://blog.csdn.net/Ricardo_XIAOHAO/article/details/132707400