当前位置: 首页 > article >正文

【Day33 LeetCode】动态规划DP Ⅵ 背包问题

一、动态规划DP Ⅵ 背包问题

1、零钱兑换 322

本质是完全背包问题,以最终的金额数amount为背包容量,不同面额的硬币为物品,物品数量无数,求装满物品需要的最少物品数。直接套用完全背包模板。由于求最少物品数是在 装满物品的方法里寻找,那么是寻找装满物品的组合 还是 排列呢?组合,因为最少物品数与顺序无关,所以采用组合即可。其实采用排列也是可以的,因为都是在结果里找到最少物品数,只是排列的结果范围更多。
下面是组合的代码:先遍历物品,再遍历背包

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount + 1, amount + 1);
        dp[0] = 0;
        for(int coin : coins)  // 先遍历物品
            for(int i=coin; i<=amount; ++i) // 再遍历背包
                dp[i] = min(dp[i], dp[i-coin] + 1);
        return dp[amount] < amount + 1 ? dp[amount] : -1;
    }
};

下面是排列的代码:先遍历背包,再遍历物品

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) {
        vector<int> dp(amount+1, amount+1);
        dp[0] = 0;
        for(int i=1; i<=amount; ++i)
            for(int coin : coins)
                if(i>=coin)
                    dp[i] = min(dp[i], dp[i-coin]+1);
        return dp[amount] < amount+1 ? dp[amount] : -1;
    }
};

2、完全平方数 279

这题与上一题零钱兑换几乎一模一样,只不过物品这里没写明,物品变成了平方小于等于背包容量的数,代码与上面几乎一模一样。
先遍历物品,再遍历背包,代码如下:

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, n);
        dp[0] = 0;
        for(int i=1; i*i<=n; ++i)  // 先遍历物品
            for(int j=i*i; j<=n; ++j)  // 再遍历背包
                dp[j] = min(dp[j], dp[j-i*i]+1);
        return dp[n];
    }
};

先遍历背包,再遍历物品,代码如下:

class Solution {
public:
    int numSquares(int n) {
        vector<int> dp(n + 1, n);
        dp[0] = 0;
        for(int i=1; i<=n; ++i)  // 先遍历背包
            for(int j=1; j*j<=n; ++j)  // 再遍历物品
                if(i - j * j >= 0)
                    dp[i] = min(dp[i], dp[i-j*j]+1);
        return dp[n];
    }
};

3、单词拆分 139

目标字符串需要由字典里的子字符串构成,相当于使用物品为字典里的字符串,且没有数量限制,装满容量为目标字符串长度的背包的方法有多少个,这是个完全背包问题。并且,对于结果来说,子字符串的结果讲究顺序,需要遍历所有顺序,所以先遍历背包,再遍历物品。代码如下:

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        unordered_set<string> wordSet;
        for(string word : wordDict)
            wordSet.insert(word);
        int n = s.size();
        vector<int> dp(n + 1);
        dp[0] = 1;
        for(int i=1; i<=n; ++i)  // 先遍历背包
            for(string word : wordSet)  // 再遍历物品
                if(i >= word.size() && s.substr(i-word.size(), word.size())==word)
                    dp[i] |=  dp[i-word.size()];
        return dp[n];
    }
};

4、多重背包问题

将每个同一种类的物品视为一个独立的物品,那么就将多重背包问题转换成了01背包问题,这样做想法简单直接,但是在扩容vector时比较耗时。
另一种代码实现更高效的方法时在循环里使用不同数量的物品。

# include<iostream>
# include<vector>

using namespace std;

int main(){
    int Capacity, N;
    cin >> Capacity >> N; // 容量  物品种类数
    vector<int> weights(N), values(N), amount(N); // 重量、价值、数量
    for(int i=0; i<N; ++i)  cin >> weights[i];
    for(int i=0; i<N; ++i)  cin >> values[i];
    for(int i=0; i<N; ++i)  cin >> amount[i];
    
    vector<int> dp(Capacity+1);
    for(int i=0; i<N; ++i) // 遍历物品
        for(int j=Capacity; j>=weights[i]; --j)  // 遍历背包
            for(int kk=1; kk<=amount[i] && j - kk * weights[i] >= 0; ++kk)
                dp[j] = max(dp[j], dp[j - kk * weights[i]] + kk * values[i]);
    cout << dp[Capacity] << endl;
    return 0;
}

二、写在后面

对于背包和物品的遍历顺序进一步加深了理解,掌握方法论解决背包问题就是套模板。


http://www.kler.cn/a/535755.html

相关文章:

  • JavaScript 中的 CSS 与页面响应式设计
  • Linux学习笔记16---高精度延时实验
  • Kafka 可靠性探究—副本刨析
  • 一个RPC框架应该解决哪些问题?
  • C语言按位取反【~】详解,含原码反码补码的0基础讲解【原码反码补码严格意义上来说属于计算机组成原理的范畴,不过这也是学好编程初级阶段的必修课】
  • CommonAPI学习笔记-2
  • SQL Server的安装和简单使用
  • SQL精度丢失:CAST(ce.fund / 100 AS DECIMAL(10, 2)) 得到 99999999.99
  • 【Uniapp-Vue3】z-paging插件组件实现触底和下拉加载数据
  • 【Elasticsearch】random_sampler聚合
  • Leecode刷题C语言之全排列②
  • Spring Boot + Spring AI快速体验
  • Polardb三节点集群部署安装--附虚拟机
  • Linux 设备驱动分类(快速理解驱动架构)
  • 《大模型面试宝典》(2025版) 发布了
  • 国自然地区基金|基于深度学习多模态影像组学智能诊断非酒精性脂肪肝病的研究|基金申请·25-02-06
  • C#项目引用VB.NET 类库项目,生成一个EXE,这是什么原理
  • 【前端】【面试】【复习详解】【react】react生命周期--函数式全解
  • 深度剖析FFmpeg视频解码后的帧处理到Qt显示 从AVFrame到QImage的转换(一)
  • “卫星-无人机-地面”遥感数据快速使用及地物含量计算的实现方法
  • 【正点原子K210连载】第六十七章 音频FFT实验 摘自【正点原子】DNK210使用指南-CanMV版指南
  • Django settings详解
  • 在C#中,Array,List,ArrayList,Dictionary,Hashtable,SortList,Stack的区别
  • 电脑可以自己换显卡吗?怎么操作
  • 洛谷题目: P8774 [蓝桥杯 2022 省 A] 爬树的甲壳虫 题解 (本题较简)
  • openGauss 3.0 数据库在线实训课程2:学习客户端工具gsql的使用