【动态规划】代码随想录算法训练营第四十六天 |139.单词拆分,关于多重背包,你该了解这些! ,背包问题总结篇!(待补充)

139.单词拆分

1、题目链接:. - 力扣(LeetCode)

2、文章讲解:代码随想录

3、题目:

给定一个非空字符串 s 和一个包含非空单词的列表 wordDict,判定 s 是否可以被空格拆分为一个或多个在字典中出现的单词。

说明:

拆分时可以重复使用字典中的单词。

你可以假设字典中没有重复的单词。

示例 1:

  • 输入: s = "leetcode", wordDict = ["leet", "code"]
  • 输出: true
  • 解释: 返回 true 因为 "leetcode" 可以被拆分成 "leet code"。

示例 2:

  • 输入: s = "applepenapple", wordDict = ["apple", "pen"]
  • 输出: true
  • 解释: 返回 true 因为 "applepenapple" 可以被拆分成 "apple pen apple"。
  • 注意你可以重复使用字典中的单词。

示例 3:

  • 输入: s = "catsandog", wordDict = ["cats", "dog", "sand", "and", "cat"]
  • 输出: false

4、视频链接:

动态规划之完全背包,你的背包如何装满?| LeetCode:139.单词拆分_哔哩哔哩_bilibili

class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        HashSet<String> set = new HashSet<>(wordDict);
        boolean[] valid = new boolean[s.length() + 1];
        valid[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (int j = 0; j < i && !valid[i]; j++) {
                if (set.contains(s.substring(j, i)) && valid[j]) {
                    valid[i] = true;
                }
            }
        }
        return valid[s.length()];
    }
}
// 另一种思路的背包算法
class Solution {
    public boolean wordBreak(String s, List<String> wordDict) {
        boolean[] dp = new boolean[s.length() + 1];
        dp[0] = true;

        for (int i = 1; i <= s.length(); i++) {
            for (String word : wordDict) {
                int len = word.length();
                if (i >= len && dp[i - len] && word.equals(s.substring(i - len, i))) {
                    dp[i] = true;
                    break;
                }
            }
        }

        return dp[s.length()];
    }
}

多重背包理论基础

对于多重背包,我在力扣上还没发现对应的题目,所以这里就做一下简单介绍,大家大概了解一下。

有N种物品和一个容量为V 的背包。第i种物品最多有Mi件可用,每件耗费的空间是Ci ,价值是Wi 。求解将哪些物品装入背包可使这些物品的耗费的空间 总和不超过背包容量,且价值总和最大。

多重背包和01背包是非常像的, 为什么和01背包像呢?

每件物品最多有Mi件可用,把Mi件摊开,其实就是一个01背包问题了。

例如:

背包最大重量为10。

物品为:

重量

价值

数量

物品0

1

15

2

物品1

3

20

3

物品2

4

30

2

问背包能背的物品最大价值是多少?

和如下情况有区别么?

重量

价值

数量

物品0

1

15

1

物品0

1

15

1

物品1

3

20

1

物品1

3

20

1

物品1

3

20

1

物品2

4

30

1

物品2

4

30

1

毫无区别,这就转成了一个01背包问题了,且每个物品只用一次。

练习题目:卡码网第56题,多重背包(opens new window)

代码如下:

// 超时了
#include<iostream>
#include<vector>
using namespace std;
int main() {
    int bagWeight,n;
    cin >> bagWeight >> n;
    vector<int> weight(n, 0); 
    vector<int> value(n, 0);
    vector<int> nums(n, 0);
    for (int i = 0; i < n; i++) cin >> weight[i];
    for (int i = 0; i < n; i++) cin >> value[i];
    for (int i = 0; i < n; i++) cin >> nums[i];    
    
    for (int i = 0; i < n; i++) {
        while (nums[i] > 1) { // 物品数量不是一的,都展开
            weight.push_back(weight[i]);
            value.push_back(value[i]);
            nums[i]--;
        }
    }
 
    vector<int> dp(bagWeight + 1, 0);
    for(int i = 0; i < weight.size(); i++) { // 遍历物品,注意此时的物品数量不是n
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
    }
    cout << dp[bagWeight] << endl;
}

大家去提交之后,发现这个解法超时了,为什么呢,哪里耗时呢?

耗时就在 这段代码:

for (int i = 0; i < n; i++) {
    while (nums[i] > 1) { // 物品数量不是一的,都展开
        weight.push_back(weight[i]);
        value.push_back(value[i]);
        nums[i]--;
    }
}

如果物品数量很多的话,C++中,这种操作十分费时,主要消耗在vector的动态底层扩容上。(其实这里也可以优化,先把 所有物品数量都计算好,一起申请vector的空间。

这里也有另一种实现方式,就是把每种商品遍历的个数放在01背包里面在遍历一遍。

代码如下:(详看注释)

#include<iostream>
#include<vector>
using namespace std;
int main() {
    int bagWeight,n;
    cin >> bagWeight >> n;
    vector<int> weight(n, 0);
    vector<int> value(n, 0);
    vector<int> nums(n, 0);
    for (int i = 0; i < n; i++) cin >> weight[i];
    for (int i = 0; i < n; i++) cin >> value[i];
    for (int i = 0; i < n; i++) cin >> nums[i];

    vector<int> dp(bagWeight + 1, 0);

    for(int i = 0; i < n; i++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            // 以上为01背包,然后加一个遍历个数
            for (int k = 1; k <= nums[i] && (j - k * weight[i]) >= 0; k++) { // 遍历个数
                dp[j] = max(dp[j], dp[j - k * weight[i]] + k * value[i]);
            }
        }
    }

    cout << dp[bagWeight] << endl;
}

时间复杂度:O(m × n × k),m:物品种类个数,n背包容量,k单类物品数量

从代码里可以看出是01背包里面在加一个for循环遍历一个每种商品的数量。 和01背包还是如出一辙的。

当然还有那种二进制优化的方法,其实就是把每种物品的数量,打包成一个个独立的包。

和以上在循环遍历上有所不同,因为是分拆为各个包最后可以组成一个完整背包,具体原理我就不做过多解释了,大家了解一下就行,面试的话基本不会考完这个深度了,感兴趣可以自己深入研究一波。

#总结

多重背包在面试中基本不会出现,力扣上也没有对应的题目,大家对多重背包的掌握程度知道它是一种01背包,并能在01背包的基础上写出对应代码就可以了。

至于背包九讲里面还有混合背包,二维费用背包,分组背包等等这些,大家感兴趣可以自己去学习学习,这里也不做介绍了,面试也不会考。

背包问题汇总

年前我们已经把背包问题都讲完了,那么现在我们要对背包问题进行总结一番。

背包问题是动态规划里的非常重要的一部分,所以我把背包问题单独总结一下,等动态规划专题更新完之后,我们还会在整体总结一波动态规划。

关于这几种常见的背包,其关系如下:

通过这个图,可以很清晰分清这几种常见背包之间的关系。

在讲解背包问题的时候,我们都是按照如下五部来逐步分析,相信大家也体会到,把这五部都搞透了,算是对动规来理解深入了。

  1. 确定dp数组(dp table)以及下标的含义
  2. 确定递推公式
  3. dp数组如何初始化
  4. 确定遍历顺序
  5. 举例推导dp数组

其实这五部里哪一步都很关键,但确定递推公式和确定遍历顺序都具有规律性和代表性,所以下面我从这两点来对背包问题做一做总结

#背包递推公式

问能否能装满背包(或者最多装多少):dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]); ,对应题目如下:

  • 动态规划:416.分割等和子集(opens new window)
  • 动态规划:1049.最后一块石头的重量 II(opens new window)

问装满背包有几种方法:dp[j] += dp[j - nums[i]] ,对应题目如下:

  • 动态规划:494.目标和(opens new window)
  • 动态规划:518. 零钱兑换 II(opens new window)
  • 动态规划:377.组合总和Ⅳ(opens new window)
  • 动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

问背包装满最大价值:dp[j] = max(dp[j], dp[j - weight[i]] + value[i]); ,对应题目如下:

  • 动态规划:474.一和零(opens new window)

问装满背包所有物品的最小个数:dp[j] = min(dp[j - coins[i]] + 1, dp[j]); ,对应题目如下:

  • 动态规划:322.零钱兑换(opens new window)
  • 动态规划:279.完全平方数(opens new window)

#遍历顺序

#01背包

在动态规划:关于01背包问题,你该了解这些!(opens new window)中我们讲解二维dp数组01背包先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

和动态规划:关于01背包问题,你该了解这些!(滚动数组)(opens new window)中,我们讲解一维dp数组01背包只能先遍历物品再遍历背包容量,且第二层for循环是从大到小遍历。

一维dp数组的背包在遍历顺序上和二维dp数组实现的01背包其实是有很大差异的,大家需要注意!

#完全背包

说完01背包,再看看完全背包。

在动态规划:关于完全背包,你该了解这些!(opens new window)中,讲解了纯完全背包的一维dp数组实现,先遍历物品还是先遍历背包都是可以的,且第二层for循环是从小到大遍历。

但是仅仅是纯完全背包的遍历顺序是这样的,题目稍有变化,两个for循环的先后顺序就不一样了。

如果求组合数就是外层for循环遍历物品,内层for遍历背包

如果求排列数就是外层for遍历背包,内层for循环遍历物品

相关题目如下:

  • 求组合数:动态规划:518.零钱兑换II(opens new window)
  • 求排列数:动态规划:377. 组合总和 Ⅳ(opens new window)、动态规划:70. 爬楼梯进阶版(完全背包)(opens new window)

如果求最小数,那么两层for循环的先后顺序就无所谓了,相关题目如下:

  • 求最小数:动态规划:322. 零钱兑换(opens new window)、动态规划:279.完全平方数(opens new window)

对于背包问题,其实递推公式算是容易的,难是难在遍历顺序上,如果把遍历顺序搞透,才算是真正理解了

#总结

这篇背包问题总结篇是对背包问题的高度概括,讲最关键的两部:递推公式和遍历顺序,结合力扣上的题目全都抽象出来了

而且每一个点,我都给出了对应的力扣题目

最后如果你想了解多重背包,可以看这篇动态规划:关于多重背包,你该了解这些!(opens new window),力扣上还没有多重背包的题目,也不是面试考察的重点。

如果把我本篇总结出来的内容都掌握的话,可以说对背包问题理解的就很深刻了,用来对付面试中的背包问题绰绰有余!

背包问题总结:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/450896.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode:206.反转链表

206. 反转链表 解题过程 /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNode next) { this.val val; this.next next; …

【C++】C++学习前言

C前言与发展 一.什么是C二.C的发展史三.C的重要性 一.什么是C C语言是结构化和模块化的语言&#xff0c;适合处理较小规模的程序。对于复杂的问题&#xff0c;规模较大的程序&#xff0c;需要高度的抽象和建模时&#xff0c;C语言则不合适。为了解决软件危机&#xff0c; 20世纪…

2023年中国抗DDoS市场规模现状及竞争格局,公有云抗DDoS是主要增长点

分布式拒绝服务&#xff08;DDoS&#xff09;是在DoS基础之上产生的一种新的攻击方式&#xff0c;具有多对一的攻击模式。它通过制造伪造的流量&#xff0c;使得被攻击的服务器、网络链路或是网络设备&#xff08;如防火墙、路由器等&#xff09;负载过高&#xff0c;无法处理正…

NUMA架构

UMA架构 在单cpu的时代&#xff0c;cpu与内存的交互需要通过北桥芯片来完成。cpu通过前端总线(FSB&#xff0c; front Side Bus)连接到北桥芯片&#xff0c;由北桥芯片连接到内存&#xff08;内存控制器是集成在北桥芯片里的&#xff09;。为了提升性能&#xff0c;cpu的频率不…

2024中国(京津冀)太阳能光伏推进大会暨展览会

2024年中国(京津冀)太阳能光伏推进大会暨展览会是一个旨在促进太阳能光伏产业发展的重要会议和展览会。该活动将在中国的京津冀地区举行&#xff0c;旨在汇聚全球太阳能光伏领域的专业人士、政府代表、企业家和科研人员&#xff0c;共同探讨太阳能光伏技术的最新进展和未来发展…

PWARL CTF and others

title: 一些复杂点的题目 date: 2024-03-09 16:05:24 tags: CTF 2024年3月9日 今日习题完成&#xff1a; 1.BUU [网鼎杯 2020 半决赛]AliceWebsite 2.[RoarCTF 2019]Online Proxy 3.[Polar CTF]到底给不给flag呢 4.网鼎杯 2020 总决赛]Game Exp [RoarCTF 2019]Online Proxy …

适合上班族的副业:steam游戏搬砖1天3小时,月入8K

互联网新时代&#xff0c;做副业的人越来越多。如果能充分利用下班后的时间&#xff0c;还真能赚到不少钱。steam游戏搬砖项目就是这样一个非常适合上班的副业&#xff0c;只要用心去操作&#xff0c;一个月至少收入两三千&#xff0c;多的轻松上万。 steam游戏搬砖项目其实做的…

【NR 定位】3GPP NR Positioning 5G定位标准解读(十四)-DL-TDOA 定位

前言 3GPP NR Positioning 5G定位标准&#xff1a;3GPP TS 38.305 V18 3GPP 标准网址&#xff1a;Directory Listing /ftp/ 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;一&#xff09;-CSDN博客 【NR 定位】3GPP NR Positioning 5G定位标准解读&#xff08;…

微信小程序(五十七)打开腾讯地图选择位置

注释很详细&#xff0c;直接上代码 前提配置看第五十四篇&#x1f427; 上一篇 新增内容&#xff1a; 1.使用地图选择位置的方法让用户重新选择大概的位置 2.留下经纬度接口以便于更新新的附近位置列表 源码&#xff1a; index.wxml <button bind:tap"chooseLocation…

java中的File

路径&#xff1a; 相对路径&#xff1a;相对路径是不带盘符的&#xff0c;它是相对于项目而言的 例如&#xff1a; “a.txt” “abc\a.txt” 绝对路径&#xff1a;绝对路径是带盘符的 &#xff0c;是相对于计算机而言。 例如&#xff1a; “C:\a.txt” “C:\abc\a.txt” Fil…

2024鸿蒙迎来大爆发,有必要转行鸿蒙开发吗?

鸿蒙开发&#xff0c;这个名字最近在科技圈引起了不小的轰动。 那么&#xff0c;鸿蒙开发到底是什么呢&#xff1f;它又能给我们带来怎样的影响呢&#xff1f; 鸿蒙开发&#xff0c;简单来说&#xff0c;就是基于鸿蒙操作系统的一种应用开发方式。鸿蒙系统&#xff0c;作为华为…

诗词生成之setting

先上代码&#xff1a; # 禁用词&#xff0c;包含如下字符的唐诗将被忽略 DISALLOWED_WORDS [&#xff08;, &#xff09;, (, ), __, 《, 》, 【, 】, [, ]] # 句子最大长度 MAX_LEN 64 # 最小词频 MIN_WORD_FREQUENCY 8 # 训练的batch size BATCH_SIZE 16 # 数据集路径 DA…

机器学习(选修)(持续更新)

Gradient Descent 1、一般我们会得到一组参数 &#xff0c;它是由很多组weight和bias组成的。 2、首先&#xff0c;我们在处理数据的时候&#xff0c;会选择一个初始化参数 3、其次&#xff0c;我们计算每个与w的偏微分&#xff0c;把他们组成矩阵的形式&#xff0c;如下图&…

C++ Qt开发:QNetworkAccessManager网络接口组件

Qt 是一个跨平台C图形界面开发库&#xff0c;利用Qt可以快速开发跨平台窗体应用程序&#xff0c;在Qt中我们可以通过拖拽的方式将不同组件放到指定的位置&#xff0c;实现图形化开发极大的方便了开发效率&#xff0c;本章将重点介绍如何运用QNetworkAccessManager组件实现Web网…

数字脉搏:互联网的演进与社会脉络

✨✨ 欢迎大家来访Srlua的博文&#xff08;づ&#xffe3;3&#xffe3;&#xff09;づ╭❤&#xff5e;✨✨ &#x1f31f;&#x1f31f; 欢迎各位亲爱的读者&#xff0c;感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢&#xff0c;在这里我会分享我的知识和经验。&am…

基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的扑克牌识别软件(Python+PySide6界面+训练代码)

摘要&#xff1a;开发扑克牌识别软件对于智能辅助决策工具的建立具有关键作用。本篇博客详细介绍了如何运用深度学习构建一个扑克牌识别软件&#xff0c;并提供了完整的实现代码。该系统基于强大的YOLOv8算法&#xff0c;并对比了YOLOv7、YOLOv6、YOLOv5&#xff0c;展示了不同…

【网站项目】010新能源汽车在线租赁

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

谷歌seo外链重要还是内容重要?

想做网站&#xff0c;内容跟外链缺一不可&#xff0c;如果真的要说哪个更重要&#xff0c;那内容依旧是网站的核心&#xff0c;而外链则是额外的加分项 内容永远是王道&#xff0c;不管谷歌seo的算法怎么变&#xff0c;只要你的内容没问题&#xff0c;那就肯定不会牵扯到你的网…

羊大师揭秘羊奶滋养,养生的新黄金选择

羊大师揭秘羊奶滋养&#xff0c;养生的新黄金选择 羊奶&#xff0c;这个自古以来的天然营养佳品&#xff0c;近年来逐渐受到现代人的青睐&#xff0c;成为养生的新黄金选择。它以其独特的营养价值和滋养功效&#xff0c;为追求健康生活的我们提供了全新的养生视角。 羊奶的滋…

SAP 批量删除工艺路线和主配方_简介

通常我们在创建工艺路线的时候或者在导入工艺路线的时候,会存在数据导入出错,或者你创建的工艺路线需要删除的情况,通常情况下我们第一个想到的就是使用CA02或者C202去删除工艺路线或者是主配方。但是这样会存在一个问题就是,首先我们知道工艺路线和主配方都是存在在组里面…