代码随想录Day44 | 完全背包 518 零钱兑换II 377 组合综合IV

本文介绍了完全背包问题的动态规划解法,包括518零钱兑换II和377组合总和IV,强调了物品选择顺序对完全背包(从物品到背包)和排列问题(从背包到物品)的重要性。
摘要由CSDN通过智能技术生成

代码随想录Day44 | 完全背包 518 零钱兑换II 377 组合综合IV

完全背包

文档讲解:代码随想录
视频讲解:
状态

物品的个数是无限个,即一个背包里可以存在同种物品。唯一区别就是遍历顺序。

  1. dp数组
    dp[j] 就表示容量为j的背包 可以选择价值最大的结果
  2. 遍历顺序
    我们01背包为什么要从后向前遍历,就是由于从前向后遍历会导致物品重复。所以对于完全背包问题我们对背包的遍历就可以从前向后遍历。
  3. 初始化
    dp[j] = 0
  4. 递推公式
    //当j >= 当前要加入物品价值时
    dp[j] = max(dp[j],dp[j-weight[i]]+value[i]
  5. 打印dp

52.携带研究材料

文档讲解:代码随想录
视频讲解:
状态

本题主要区别就是每个研究材料可以无限选择,那么我们就可以更改遍历顺序,然后更新递推公式就可以求解

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    int N,V;
    cin >> N >> V;
    vector<vector<int>> coll(N,vector<int>(2,0));
    for(int i = 0;i<N;i++)
    {
        cin >> coll[i][0] >> coll[i][1];
    }
    
    //dp数组
    vector<int> dp(V+1,0);
    
    for(int i = 0;i<N;i++)
    {
        for(int j = 0;j<V+1;j++)
        {
            if(j >= coll[i][0])
                dp[j] = max(dp[j],dp[j-coll[i][0]]+coll[i][1]);
        }
    }
    
    cout << dp[V];
    
    return 0;
}

518.零钱兑换II

文档讲解:代码随想录
视频讲解: 装满背包有多少种方法?组合与排列有讲究!| LeetCode:518.零钱兑换II
状态

相当于就是容量为amount的背包,从coins物品中选择刚好填满背包有多少种方法

  1. dp数组
    dp[j] 表示 容量为j的背包 有多少种方法填满
  2. 递推公式
    当j > coins[i]时,dp[j]+=dp[j-coins[i]];
  3. 遍历顺序
    先物品再背包,重复计算物品 背包从前向后
    循环是否能够调换–>组合还是排列,这道题的要求显然是组合问题,即不考虑元素顺序对结果的影响。所以不能够调换背包和物品的循环,如果是组合问题,那么就需要考虑顺序影响,那么调换循环的先后就没有关系。
  4. 初始化
    dp[0] = 1
  5. 打印dp数组
//容量为amout的背包,有多少种选择方式
class Solution {
public:
    int change(int amount, vector<int>& coins) {
        vector<int> dp(amount+1,0);
        dp[0] = 1;
        for(int i = 0;i<coins.size();i++)
        {
            //背包
            for(int j = 0;j<amount+1;j++)
            {
                if(j >= coins[i])
                {
                    dp[j] += dp[j-coins[i]];
                }
            }
        }
        return dp[amount];
    } 
};

377.组合总和Ⅳ

文档讲解:代码随想录
视频讲解: 装满背包有几种方法?求排列数?| LeetCode:377.组合总和IV
状态

本题就属于是排列问题了,使用回溯方法来解决是超时的。
考虑动态规划

  1. dp数组
    dp[j]表示的就是对于和为j的话有多少种排列数
  2. 递推公式
    如果j>nums[i] dp[j] += dp[j-nums[i]]
  3. 初始化
    dp[0] = 1
  4. 遍历顺序
    考虑排列,先背包再物品
  5. 打印dp
//动态规划
class Solution {
public:
    int combinationSum4(vector<int>& nums, int target) {
        vector<int> dp(target+1,0);
        dp[0] = 1;
        for(int j = 0;j<target+1;j++)
        {
            for(int i = 0;i<nums.size();i++)
            {
                if(j >= nums[i] && dp[j] <INT_MAX-dp[j-nums[i]])
                {
                    dp[j] += dp[j-nums[i]];
                }
            }
        }
        return dp[target];
    }
};

在这里插入图片描述
给定数组中可能存在两个数相加超过INT的情况

对于完全背包 求组合就先物品再背包,相当于物品是按照升序选取
求排列就先背包再物品, 物品乱序实现排列

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值