算法训练营DAY46|139.单词拆分、多重背包的介绍

news2024/11/24 14:55:57

这一期到了背包问题的最后一期,主要讲解一道leetcodee题,和对多重背包的一些简单介绍,由于leetcode没有对于多重背包的具体问题,且面试基本不会问到多重背包所以只是作为科普。

139. 单词拆分 - 力扣(LeetCode)https://leetcode.cn/problems/word-break/给定一个字符串要求将其拆分,拆分后的各部分单词都可以在给我们的字符串字典里找到,也就是说该字符串是由该字符串字典的某些单词拼接而成。字符串字典里每个单词都可以重复使用。

这道题是分割字符串问题,也可以用回溯算法来求解。这里不做这方面的讲解

无论是回溯算法还是完全背包的模型解决问题,都涉及到一个很重要的问题,如果不能想通,则问题将无法得到解决,我们在下面分析时候再做详细讲解。

动规分析

dp数组的含义:dp【i】指的是对于该字符串截止到第i个字符是否能由字符串字典里的字符串组成,如果能则dp【i】=true,否则则为false。

递推公式:dp【i】是否为真主要由两部分推测得来,一部分是我们要判断的这个字符串中由i到j的这个字符串是否在字典里出现过,另一部分是我们要判断的这个字符串它的前面如果有字符串那么它前面的字符串也必须是true,也就是说也必须由字符串字典的某些字符串构成,满足两者关系同时存在时,才能判定从头到现在的位置,为true。这一点很重要无论是回溯算法,还是用动态规划都要想出来,否则题目无法解出。

dp数组的初始化:根据递推公式得,由于dp【i】的推理依赖于前一个状态,所以dp【0】必须要初始化为true,否则最后不可能为true,其余的部分初始化为false即可。

遍历顺序:完全背包中的遍历顺序大多数都有考究的,不像01背包的一维数组实现,基本都是一样的遍历方法。这道题从排列组合的角度上思考,是要依靠排列的思想来写代码遍历,因为我们字符串字典里的字符串组成给定的字符串,是一定要有顺序的,顺序不对是无法拼接的。所以是先遍历背包再遍历物品。从直接看先遍历背包还是物品的角度来讲,如果先遍历物品再遍历背包,那么物品从前向后遍历只能遍历一次,无法达到物品可以重复使用的效果!这样推算下来肯定是有错误的,所以要先遍历背包。

class Solution {
public:
    bool wordBreak(string s, vector<string>& wordDict) {
        set<string>wordset(wordDict.begin(),wordDict.end());
        vector<bool>dp(s.size()+1,false);
        dp[0]=true;
        for(int i=1;i<=s.size();i++){
            for(int j=0;j<=i;j++){
                string word=s.substr(j,i-j);
                if(wordset.find(word)!=wordset.end()&&dp[j]==true)
                    dp[i]=true;
            }   
        }
        return dp[s.size()];
    }
};

多重背包是和01背包有相像之处的模型。给我们的物品,价值不同且每件物品都有有限个,也就是说物品件数不一定是1,但也不是无限的,可能是2,3,4个,求怎样装使背包容量之内获得价值最高。那么为什么说它和01背包有相似之处呢?这是由于我们可以将物品个数大于1的物品展开,比如有一物品价值15有两个,我们可以展开为价值15有一个,和价值15有一个。这样不就展开为01背包了吗。根据这样的思路得到如下代码。

void test_multi_pack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    vector<int> nums = {2, 3, 2};
    int bagWeight = 10;
    for (int i = 0; i < nums.size(); i++) {
        while (nums[i] > 1) { // 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++) { // 遍历物品
        for(int j = bagWeight; j >= weight[i]; j--) { // 遍历背包容量
            dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
        }
        for (int j = 0; j <= bagWeight; j++) {
            cout << dp[j] << " ";
        }
        cout << endl;
    }
    cout << dp[bagWeight] << endl;

}
int main() {
    test_multi_pack();
}

如果不展开物品的话,还有另一种方法。就是在背包里重复遍历该物品。

void test_multi_pack() {
    vector<int> weight = {1, 3, 4};
    vector<int> value = {15, 20, 30};
    vector<int> nums = {2, 3, 2};
    int bagWeight = 10;
    vector<int> dp(bagWeight + 1, 0);


    for(int i = 0; i < weight.size(); 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]);
            }
        }
        // 打印一下dp数组
        for (int j = 0; j <= bagWeight; j++) {
            cout << dp[j] << " ";
        }
        cout << endl;
    }
    cout << dp[bagWeight] << endl;
}
int main() {
    test_multi_pack();
}

我认为还是第一种方法比较好理解,对于第二种方法的递推公式,理解上可能有一点别扭。


以上即全部内容,对背包问题感兴趣的朋友,可以去看我的其他文章,还有对于背包基础和背包各应用的具体讲解。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

缺省参数,函数重载,引用的使用(C++)

前言 本文主要讲解的是缺省参数&#xff0c;函数重载&#xff0c;引用的使用. 文章目录 目录 前言 一、缺省参数是什么&#xff1f; 1.缺省参数的分类 二、函数重载是什么&#xff1f; 三、引用是什么&#xff1f; 1.引用特性 总结 提示&#xff1a;以下是本篇文章正文内容&am…

java中的NIO,BIO,AIO

IO&#xff0c;input和output&#xff0c;Java 为 I/O 提供了强大的而灵活的支持&#xff0c;使其更广泛地应用到文件传输和网络编程中。 IO是什么&#xff1f;为什么需要IO&#xff1f; java在1.4之前&#xff0c;提供的是BIO&#xff0c;也就是java.io包下的的东西&#xf…

SpringBoot(二):配置文件的作用、配置文件的格式、properties配置文件、yml配置文件

目录一、配置文件的作用二、配置文件的格式三、properties配置文件3.1 properties的基本语法3.2 properties的缺点3.3 配置自定义内容3.4 读取配置文件四、yml配置文件4.1 yml基本介绍4.2 yml基本语法4.3 使用yml配置不同的数据类型4.4 读取yml配置文件4.5 在yml中配置对象4.6 …

关于UWB汽车钥匙介绍

汽车钥匙经历了机械钥匙、遥控钥匙、PEPS、数字钥匙四个阶段&#xff0c;而数字钥匙又分为BLE/NFC/UWB三种技术路线。由于UWB安全性、定位精度、作用范围明显好于BLE和NFC&#xff0c;因此成为汽车数字钥匙的最优技术。PEPS与数字钥匙PEPS是指无钥匙进入/无钥匙启动系统&#x…

MySQL详解(三)——高级 1.0

MySQL高级 utf8只支持每个字符最多三个字节&#xff0c;而真正的 UTF-8 是每个字符最多四个字节 MySQL 的这个bug一直没有被修复&#xff0c;他们在 2010 年发布了一个叫作“utf8mb4”的字符集&#xff0c;绕过了这个问题。 MySQL优点 Mysql是开源的Mysql是可以定制的&…

CDN的那些事

CDN的那些事一、前言二、基础配置三、访问控制四、缓存配置五、HTTPS配置六、高级配置&#xff08;最重点来了&#xff09;七、结语一、前言 大家好&#xff0c;我是尝试中成长的站长&#xff0c;前段时间&#xff0c;群友的cdn被刷爆了&#xff0c;这就引起了我的恐慌&#x…

读书笔记:神经网络加法层与乘法层的实现及应用 buy_apple_orange.py ← 斋藤康毅

“层”是神经网络中功能的单位。通常把神经网络的“层”实现为一个类。“层”的实现中有两个共通的方法 forward() 和 backward()。forward() 对应正向传播&#xff0c;backward() 对应反向传播。加法结点的反向传播将上游的值原封不动地输出到下游&#xff0c;乘法结点的反向传…

第2章:使用CSS定义样式

在前一章中,我们研究了Java代码的不同片段。 在本章中,我们将对每个示例使用相同的代码段: public void createPdf(String html, String dest) throws IOException {HtmlConverter.convertToPdf(html, new FileOutputStream(dest)); } 我们不看Java代码的不同片段,而是看…

数据分析-深度学习Pytorch Day13

单层感知机和多层感知机(MLP)是最基础的神经网络结构。将卷积操作创新的加入到神经网络结构形成了卷积神经网络&#xff0c;卷积神经网络给现代人工智能注入了活力。感知机网络和卷积网络(CNN)都属于前馈型网络(FeedForward Network)。单层感知机是二分类的线性分类模型&#x…

MT1010-M1016(java版)

MT1010输入和输出字符型数据难度&#xff1a;青铜0时间限制&#xff1a;1秒巴占用内存&#xff1a;64M★收藏△报错请编写一个简单程序&#xff0c;用户输入2个的字符型数据存储在变量中&#xff0c;并分别以字符形式和整数形式输出在屏幕上。格式输入格式&#xff1a;2个的字符…

Go语言DDD实战初级篇

导读 领域驱动设计(DDD)最简洁的描述可能是&#xff1a;如何在明确的限界上下文中创建通用语言的模型。通过 DDD思想设计开发的软件&#xff0c;在领域专家、开发者和软件本身之间不存在“翻译”&#xff0c;三者通过在限界上下文下的通用语言直接表示。而这个系列则是我们团队…

交换机——VLAN原理和基本配置

VLAN原理和配置VLAN的三种端口类型Access&#xff1a;接入链路类型&#xff08;一般使用&#xff1a;交换机与PC&#xff09;Trunk&#xff1a;干道链路类型&#xff08;一般使用&#xff1a;交换机与交换机&#xff09;Hybrid在这里&#xff0c;我们只使用和讲解Access和Trunk…

HTML简介

目录 一、HTML基础知识 二、HTML常见标签 注释标签 标题标签 段落标签 常用的转义字符 换行标签 格式化标签 图片标签 超链接标签 表格标签 列表标签 input标签 文本框 密码框 单选框 复选框 普通按钮 选择文件 下拉标签 多行文本输入 无语…

【哈希表】leetcode454.四数相加II(C/C++/Java/Python/Js)

leetcode454.四数相加II1 题目2 思路3 代码3.1 C版本3.2 C版本3.3 Java版本3.4 Python版本3.5 JavaScript版本4 总结需要哈希的地方都能找到map的身影 1 题目 题源链接 给你四个整数数组 nums1、nums2、nums3 和 nums4 &#xff0c;数组长度都是 n &#xff0c;请你计算有多少…

C中线程信号控制

一、场景介绍存在三个线程&#xff0c;一个主线程和两个子线程&#xff08;子线程数量不固定&#xff09;。为了节省频繁创建销毁线程造成的资源浪费&#xff0c;将这些线程设置为常驻线程。但这样引入了一个新的问题&#xff0c;如何协调这些线程完成工作。主线程内是循环检测…

Webgl实现的天气效果(下雨、下雪)

一、下雨效果如图&#xff1a; 还有一种雨水效果也不错 114 Three.js实现深度遮挡的下雨特效 | 暮志未晚-中文案例网 二、下雪的效果 57 Three.js 使用粒子实现下雪特效 | 暮志未晚-中文案例网 还有一种是通过网页CSS的形式做的2D雪效果 集合在一起的源码&#xff1a; https…

编译原理学习笔记17——语义分析和中间代码生成2

编译原理学习笔记17——语义分析和中间代码生成217.1 赋值语句的翻译17.2数组元素引用的翻译17.3 类型转换17.1 赋值语句的翻译 简单算术表达式及赋值语句 赋值语句生成三地址代码的S-属性文法 赋值语句生成三地址代码的S-属性文法 产生赋值语句三地址代码的翻译模式 产…

你真的了解工厂设计模式吗?(简单工厂模式+工厂方法模式+抽象工厂模式)

工厂解决的问题 客户端在调用是不想判断实例化哪一个类或者实例化的过程过于复杂。在工厂模式中&#xff0c;具体的实现类创建过程对客户端是透明的&#xff0c;客户端不决定具体实例化哪一个类&#xff0c;而是交由“工厂”来实例化。 简单工厂模式 类图 简单工厂模式由三类…

Git GitHub纯新手入门教程

参考视频&#xff1a;Github 新手够用指南 | 全程演示&个人找项目技巧放送_哔哩哔哩_bilibili40 分钟学会 Git | 日常开发全程大放送&个搭配GitHub_哔哩哔哩_bilibiliGit和GitHub分别是什么Git是一个运行在电脑上的版本控制软件&#xff08;保存代码各个阶段历史记录的…

在使用定时器过程中存在的那些陷阱

在使用定时器的过程中&#xff0c;如果你不了解定时器的一些细节&#xff0c;那么很有可能掉进定时器的一些陷阱里&#xff0c;函数 setTimeout 在时效性上面有很多先天的不足&#xff0c;所以对于一些时间精度要求比较高的需求&#xff0c;应该有针对性地采取一些其他的方案 …