代码随想录第四十四天|完全背包理论基础、518零钱兑换、377组合总和

文章介绍了使用动态规划解决完全背包问题和组合问题的方法,包括01背包的变种。在完全背包问题中,物品可以无限次放入背包,通过从小到大的遍历顺序优化求解最大价值。在零钱兑换和组合总和问题中,利用dp数组记录达到特定金额的组合数或排列数,通过递推公式更新状态并遍历所有可能的硬币面额或数组元素。
摘要由CSDN通过智能技术生成

完全背包

有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次),求解将哪些物品装入背包里物品价值总和最大。

01背包和完全背包唯一不同就是体现在遍历顺序上,完全背包的物品是可以添加多次的,所以要从小到大去遍历。

// 先遍历物品,在遍历背包
void test_CompletePack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    int bagWeight = 4;
    vector<int> dp(bagWeight + 1, 0);
    for(int i = 0; i < weight.size(); i++) { // 遍历物品
        for(int j = weight[i]; j <= bagWeight; j++) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }
    cout << dp[bagWeight] << endl;
}
int main() {
    test_CompletePack();
}

518.零钱兑换

给定不同面额的硬币和一个总金额。写出函数来计算可以凑成总金额的硬币组合数。假设每一种面额的硬币有无限个。

1)确定dp数组及下标含义

dp[j]:凑成总金额j的货币组合数为dp[j]。

2)确定递推公式

dp[j] += dp[j - coins[i]]。

3)dp数组初始化

dp[0] = 1。

4)确定遍历顺序

外层for循环遍历物品(钱币),内层for遍历背包(金钱总额)。(代表组合数)

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=coins[i];j<=amount;j++) {
                dp[j] += dp[j-coins[i]];
            }
        }
        return dp[amount];
    }
};

377.组合总和

给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数。

1)确定dp数组及下标含义

dp[i]: 凑成目标正整数为i的排列个数为dp[i]。

2)确定递推公式

dp[i] += dp[i - nums[j]]。

3)dp数组初始化

dp[0] = 1。

4)确定遍历顺序

外层for遍历背包,内层for循环遍历物品。(代表排列数)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值