代码训练营 day39|0-1背包问题,LeetCode 416

前言

这里记录一下陈菜菜的刷题记录,主要应对25秋招、春招
个人背景
211CS本+CUHK计算机相关硕,一年车企软件开发经验
代码能力:有待提高
常用语言:C++

系列文章目录

第九章 动态规划part03


`

文章目录

  • 前言
  • 系列文章目录
    • 第九章 动态规划part03
  • 一、今日任务
  • 二、详细布置
      • 背包问题详解
        • 二维数组版本
          • dp数组定义
          • dp递推公式
          • dp数组初始化
          • 确定遍历顺序
        • 一维数组版本
          • 确定dp数组的定义
          • 一维dp数组的递推公式
          • 一维dp数组遍历顺序
          • 初始化
      • 46. 携带研究材料
        • 提示:
        • 样例1:
        • 思路
        • 实战
        • 一维数组求解法
      • 416. 分割等和子集
        • 提示:
        • 样例1:
        • 样例2:
        • 思路
        • 实战
    • 总结



一、今日任务

● 01背包问题 二维
● 01背包问题 一维
● 416. 分割等和子集

二、详细布置

背包问题详解

在这里插入图片描述
完全背包又是也是01背包稍作变化而来,即:完全背包的物品数量是无限的

二维数组版本
dp数组定义

dp[i][j] 表示从下标为[0-i]的物品里任意取,放进容量为j的背包,价值总和最大是多少。(i 来表示物品、j表示背包容量)

dp递推公式

-不放物品i:背包容量为j,里面不放物品i的最大价值是dp[i - 1][j]。
-放物品i:背包空出物品i的容量后,背包容量为j - weight[i],dp[i - 1][j - weight[i]] 为背包容量为j - weight[i]且不放物品i的最大价值,那么dp[i - 1][j - weight[i]] + value[i] (物品i的价值),就是背包放物品i得到的最大价值
递归公式: dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

dp数组初始化

首先从dp[i][j]的定义出发,如果背包容量j为0的话,即dp[i][0],无论是选取哪些物品,背包价值总和一定为0。
在看其他情况。

状态转移方程 dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]); 可以看出i 是由 i-1 推导出来,那么i为0的时候就一定要初始化。

dp[0][j],即:i为0,存放编号0的物品的时候,各个容量的背包所能存放的最大价值。

那么很明显当 j < weight[0]的时候,dp[0][j] 应该是 0,因为背包容量比编号0的物品重量还小。

当j >= weight[0]时,dp[0][j] 应该是value[0],因为背包容量放足够放编号0物品。

for (int j = 0 ; j < weight[0]; j++) {  // 当然这一步,如果把dp数组预先初始化为0了,这一步就可以省略,但很多同学应该没有想清楚这一点。
    dp[0][j] = 0;
}
// 正序遍历
for (int j = weight[0]; j <= bagweight; j++) {
    dp[0][j] = value[0];
}

最后初始化代码如下:

// 初始化 dp
vector<vector<int>> dp(weight.size(), vector<int>(bagweight + 1, 0));
for (int j = weight[0]; j <= bagweight; j++) {
    dp[0][j] = value[0];
}
确定遍历顺序

先遍历物品更好理解

// weight数组的大小 就是物品个数
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    for(int j = 0; j <= bagweight; j++) { // 遍历背包容量
        if (j < weight[i]) dp[i][j] = dp[i - 1][j];
        else dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);

    }
}
一维数组版本
确定dp数组的定义

dp[j]表示:容量为j的背包,所背的物品价值可以最大为dp[j]

一维dp数组的递推公式

dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);

一维dp数组遍历顺序
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]);

    }
}

注意:这里和二维dp的写法中,遍历背包的顺序是不一样的!

二维dp遍历的时候,背包容量是从小到大,而一维dp遍历的时候,背包是从大到小。
倒序遍历是为了保证物品i只被放入一次!
代码中是先遍历物品嵌套遍历背包容量,那可不可以先遍历背包容量嵌套遍历物品呢?

不可以!

初始化

dp数组在推导的时候一定是取价值最大的数,如果题目给的价值都是正整数那么非0下标都初始化为0就可以了。

这样才能让dp数组在递归公式的过程中取的最大的价值,而不是被初始值覆盖了。

46. 携带研究材料

题目链接:卡码网46
文章讲解:代码随想录

小明是一位科学家,他需要参加一场重要的国际科学大会,以展示自己的最新研究成果。他需要带一些研究材料,但是他的行李箱空间有限。这些研究材料包括实验设备、文献资料和实验样本等等,它们各自占据不同的空间,并且具有不同的价值。

小明的行李空间为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料只能选择一次,并且只有选与不选两种选择,不能进行切割。

输入:
第一行包含两个正整数,第一个整数 M 代表研究材料的种类,第二个正整数 N,代表小明的行李空间。

第二行包含 M 个正整数,代表每种研究材料的所占空间。

第三行包含 M 个正整数,代表每种研究材料的价值。

输出:
输出一个整数,代表小明能够携带的研究材料的最大价值

提示:

数据范围:
1 <= N <= 5000
1 <= M <= 5000
研究材料占用空间和价值都小于等于 1000

样例1:
输入:
1 6 1
2 2 3 1 5 2
2 3 1 5 4 3
输出:
5
解释:
小明能够携带 6 种研究材料,但是行李空间只有 1,而占用空间为 1 的研究材料价值为 5,所以最终答案输出 5
思路

这题就是0-1背包问题的经典应用。

实战

#include <bits/stdc++.h>
using namespace std;
int main(){
    int M,N;
    cin>>M>>N;
    vector<int> weight(M,0);
    vector<int> value(M,0);
    vector<vector<int>> dp(M,vector<int>(N+1,0));
    int i,j;
    for(i=0;i<M;i++){
        cin>>weight[i];
    }
    for(j=0;j<M;j++){
        cin>>value[j];
    }
    for(j=weight[0];j<=N;j++){
            dp[0][j]=value[0];
    }
    for(i=1;i<M;i++){
        for(j=0;j<=N;j++){
            if(j<weight[i])
                dp[i][j]=dp[i-1][j];
            else
                dp[i][j]=max(dp[i-1][j],dp[i-1][j-weight[i]]+value[i]);
        }
    }
    cout<<dp[M-1][N]<<endl;
    return 0;
}

一维数组求解法
#include <bits/stdc++.h>
using namespace std;
int main(){
    int n,bagweight;
    cin>>n>>bagweight;
    vector<int> weight(n,0);
    vector<int> value(n,0);
    int i,j;
    for(i=0;i<n;i++)
        cin>>weight[i];
    for(j=0;j<n;j++)
        cin>>value[j];
    vector<int> dp(bagweight+1,0);
    
    for(i=0;i<n;i++){
        for(j=bagweight;j>=weight[i];j--){
            dp[j]=max(dp[j],dp[j-weight[i]]+value[i]);
        }
    }
    cout<<dp[bagweight]<<endl;
    return 0;
}

416. 分割等和子集

题目链接:LeetCode426
文章讲解:图文讲解

题目描述

给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集,使得两个子集的元素和相等。

提示:

1 <= nums.length <= 200
1 <= nums[i] <= 100

样例1:
输入:nums = [1,5,11,5]
输出:true
解释:数组可以分割成 [1, 5, 5][11] 
样例2:
输入:nums = [1,2,3,5]
输出:false
解释:数组不能分割成两个元素和相等的子集。
思路

0-1背包的变形。

实战
class Solution {
public:
    bool canPartition(vector<int>& nums) {
        int sum=0;
        for(auto num:nums){
            sum+=num;
        }
        if(sum%2!=0)
            return false;
        int n=nums.size(),bagweight=sum/2;
        vector<int> dp(bagweight+1,0);
        int i,j;
        for(i=0;i<n;i++){
            for(j=bagweight;j>=nums[i];j--){
                dp[j] = max(dp[j], dp[j - nums[i]] + nums[i]);
            }
        }
        if(dp[bagweight]==bagweight)
            return true;
        return false;
    }
};

总结

今天主要学习了0-1背包问题,老师讲的很详细,理解起来不难。后面还需要多做题巩固一下代码。
加油,坚持打卡的第39天。

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

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

相关文章

GDAL+C#实现矢量多边形转栅格

1. 开发环境测试 参考C#配置GDAL环境&#xff0c;确保GDAL能使用&#xff0c;步骤简述如下&#xff1a; 创建.NET Framework 4.7.2的控制台应用 注意&#xff1a; 项目路径中不要有中文&#xff0c;否则可能报错&#xff1a;can not find proj.db 在NuGet中安装GDAL 3.9.1和G…

达梦数据库性能优化

1、SQL执行计划 拿到一条SQL的时候&#xff0c;首先要下达梦手册中提出的有效SQL规范&#xff0c;及是否命中了特殊OR子句的不规范&#xff0c;是否用了复杂的正则表达式&#xff0c;避免重复很高的索引&#xff0c;UINON ALL 是否可以替换UNION操作等,某些场景INSTR函数导致的…

ParallelsDesktop20最新版本虚拟机 一键切换系统 游戏娱乐两不误

让工作生活更高效&#xff1a;Parallels Desktop 20最新版本虚拟机的神奇之处 大家好&#xff01;&#x1f44b; 今天我要跟大家安利一款让我工作效率飞升的神器——Parallels Desktop 20最新版本虚拟机。作为一个日常需要在不同操作系统间来回穿梭的人&#xff0c;这款软件简直…

【升华】python基础包NumPy学习

NumPy是使用Python进行科学计算的基础软件包。除其他外&#xff0c;它包括&#xff1a; 功能强大的N维数组对象。精密广播功能函数。集成 C/C和Fortran 代码的工具。强大的线性代数、傅立叶变换和随机数功能。 # 1、安装包 $ pip install numpy# 2、进入python的交互式界面 $…

从零开始学PHP之helloworld

前言 每一门编程语言的第一个程序就是输出hell world&#xff08;别杠&#xff0c;杠就是你对&#xff09; 开始 上一篇讲完了开发环境的安装&#xff0c;这次讲编辑器的安装&#xff0c;顺带完成上一篇的作业&#xff08;输出hello world&#xff09; 安装PHPstorm 我用的…

前端布局与响应式设计综合指南(末)

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Css篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来Css篇专栏内容:前端布局与响应式设计综合指南(末) 目录 61、为什么要初始化CSS样式 62、CSS3 有哪些新特性 63、…

【python】NumPy(三):文件读写

目录 ​前言 NumPy 常见IO函数 save()和load() savez() loadtxt()和savetxt() 练习 前言 在数据分析中&#xff0c;我们经常需要从文件中读取数据或者将数据写入文件&#xff0c;常见的文件格式有&#xff1a;文本文件txt、CSV格式文件&#xff08;用逗号分隔&#xff…

vue-router钩子中调用ElMessage等样式出错

升级 vue3.5 时遇到奇怪的问题, 页面点击离开没反应 经过排查, 是以下几点相互作用导致此问题 vue 有应用上下文的概念, 例如 runWithContext API,vue-router 在调用钩子时会获取 vue 的应用上下文element-plus 在唤起弹窗时会从 parent 或 应用上下文上拿到 config 信息eleme…

大数据环境 hbase+ phoenix idea

1、选择jdk 2、添加驱动 3、添加数据源

【精选】基于javaweb的流浪动物领养系统(源码+定制+开发)

博主介绍&#xff1a; ✌我是阿龙&#xff0c;一名专注于Java技术领域的程序员&#xff0c;全网拥有10W粉丝。作为CSDN特邀作者、博客专家、新星计划导师&#xff0c;我在计算机毕业设计开发方面积累了丰富的经验。同时&#xff0c;我也是掘金、华为云、阿里云、InfoQ等平台…

《重置MobaXterm密码并连接Linux虚拟机的完整操作指南》

目录 引言 一、双击MobaXterm_Personal_24.2进入&#xff0c;但是忘记密码。 那么接下来请跟着我操作。 二、点击此链接&#xff0c;重设密码。 三、下载完成后&#xff0c;现在把这个exe文件解压。注意解压要与MobaXterm_Personal_24.2.exe在同一目录下哦&#xff0c;不然…

从零入门AI篡改图片检测(金融场景)#Datawhale十月组队学习

1.大赛背景 在全球人工智能发展和治理广受关注的大趋势下&#xff0c;由中国图象图形学学会、蚂蚁集团、云安全联盟CSA大中华区主办&#xff0c;广泛联合学界、机构共同组织发起全球AI攻防挑战赛。本次比赛包含攻防两大赛道&#xff0c;分别聚焦大模型自身安全和大模型生成内容…

pc轨迹回放制作

亲爱的小伙伴&#xff0c;在您浏览之前&#xff0c;烦请关注一下&#xff0c;在此深表感谢&#xff01; 课程主题&#xff1a;pc轨迹回放制作 主要内容&#xff1a;制作车辆轨迹操作页&#xff0c;包括查询条件、动态轨迹回放、车辆轨迹详情表单等 应用场景&#xff1a;车辆…

sqli-labs less-25a

Sqli-labs less-25a 判断注入类型&#xff0c;列数及注入点 构造 http://192.168.140.130/sq/Less-25a/?id1 回显正常 http://192.168.140.130/sq/Less-25a/?id1’ 报错 构造 http://192.168.140.130/sq/Less-25a/?id1 and 11 回显正常 http://192.168.140.130/sq/Less-25a…

RabbitMQ 入门(三)SpringAMQP五种消息类型(Basic Queue)

一、Spring AMQP 简介 SpringAMQP是基于RabbitMQ封装的一套模板&#xff0c;并且还利用SpringBoot对其实现了自动装配&#xff0c;使用起来非常方便。 SpringAmqp的官方地址&#xff1a;https://spring.io/projects/spring-amqp SpringAMQP提供了三个功能&#xff1a; - 自动…

唐布拉不是家,而我途径它(一)

唐布拉不是家&#xff0c;而我途径它 旅途是一本书&#xff0c;风吹哪页读哪页&#xff0c;笔搁哪句写哪句。 最后一站在唐布拉的尼勒克&#xff0c;晚上11点才到&#xff0c;车停在门口&#xff0c;打开车门就看到这句话&#xff1a; 希望你快乐 今天 明天 天天刚下完雨&am…

2024年诺贝尔物理学奖揭晓:AI背后的“造梦者”是谁?

想象一下&#xff0c;你早上醒来&#xff0c;智能音箱为你播放天气和新闻&#xff0c;中午你用手机刷视频&#xff0c;精准的推荐内容简直和你心有灵犀&#xff0c;晚上回家&#xff0c;自动驾驶汽车安全地把你送回家。这一切看似理所当然&#xff0c;背后却有一双无形的手推动…

双向链表常见接口实现

一 . 链表的分类 链表的结构非常多样,以下情况组合起来就有8种( 2 * 2 * 2 ) 链表结构 : 1.1 单向/双向 1 . 单向 : 只能往一个方向遍历 (仅有一个指针 --> 指向下一个结点的地址), 如下图 : 只能从d1找到d2 , d2 找不到d1 2 . 双向 : 能从两个方向遍历 ( 有指向下一个结点…

Leetcode 841. 钥匙和房间

1.题目基本信息 1.1.题目描述 有 n 个房间&#xff0c;房间按从 0 到 n – 1 编号。最初&#xff0c;除 0 号房间外的其余所有房间都被锁住。你的目标是进入所有的房间。然而&#xff0c;你不能在没有获得钥匙的时候进入锁住的房间。 当你进入一个房间&#xff0c;你可能会在…

深度解析服务级别协议(SLA):保障业务稳定性的关键承诺

前言&#xff1a; 在当今数字化时代&#xff0c;企业的业务连续性和稳定性至关重要。服务级别协议&#xff08;SLA&#xff09;作为服务提供商与客户之间的正式承诺&#xff0c;是确保服务质量、可用性、责任的重要工具。SLA不仅定义了服务提供商应达到的服务指标&#xff0c;还…