3.8 动态规划 背包问题

news2024/12/23 22:06:37

一.01背包

46. 携带研究材料(第六期模拟笔试) (kamacoder.com)

代码随想录 (programmercarl.com)

携带研究材料:

时间限制:5.000S  空间限制:128MB

题目描述:

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

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

输入描述:

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

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

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

输出描述:

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

输入示例:

6 1
2 2 3 1 5 2
2 3 1 5 4 3

 1.dp状态描述

dp[i][j]表示前i个物品中行李空间为j时能带的最大价值   

space[i]表示i物品所需空间

value[i]表示i物品的价值

2.递推公式

先遍历物品再遍历背包空间时
新来一个物品i时面对两种情况 带或不带,带的前提是当前空间>新物品空间I
if(j>=space[i]) dp[i][j]=max(dp[i-1][j-space[i]]+value[i],dp[i-1][j]);
else dp[i][j]=dp[i-1][j]

3. 初始状态

是从一个一个物品开始遍历,初始状态有第一个物品即可(第一行)

    for(int i=0;i<=n;i++)
    {
        if(i>=space[0]) dp[0][i]=value[0];
    }

4.遍历顺序

先遍历物品或背包都可以,但遍历物品更好理解

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int m = 0, n = 0;
    cin >> m >> n;
    vector<int> space,value;
    int tempM=m;
    while(tempM--)
    {
        int tempSpace;
        cin>>tempSpace;
        space.push_back(tempSpace);
    }
    tempM=m;
    while(tempM--)
    {
        int tempValue;
        cin>>tempValue;
        value.push_back(tempValue);
    }
    // for(auto e : space) cout<<e;
    // for(auto e : value) cout<<e;
    //每一个带可能带或不带,前面的选择会影响后面
    //dp[i][j]表示前i个物品中行李空间为j时能带的最大价值   
    //新来一个物品i时面对两种情况 带或不带
    //if(j>=space[i]) dp[i][j]=max(dp[i-1][j-space[i]]+value[i],dp[i-1][j]);
    //else dp[i][j]=dp[i-1][j]
    vector<vector<int>> dp(m,vector<int>(n+1,0));
    // //初始状态第一行即可
    for(int i=0;i<=n;i++)
    {
        if(i>=space[0]) dp[0][i]=value[0];
    }
    for(int i=1;i<m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(j>=space[i]) dp[i][j]=max(dp[i-1][j-space[i]]+value[i],dp[i-1][j]);
            else dp[i][j]=dp[i-1][j];
        }
    }
    cout<<dp[m-1][n];
    return 0;
}

 二.完全背包

52. 携带研究材料(第七期模拟笔试) (kamacoder.com)

代码随想录 (programmercarl.com)

52. 携带研究材料(第七期模拟笔试)

时间限制:1.000S  空间限制:128MB

题目描述:

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

小明的行李箱所能承担的总重量为 N,问小明应该如何抉择,才能携带最大价值的研究材料,每种研究材料可以选择无数次,并且可以重复选择。

输入描述:

第一行包含两个整数,N,V,分别表示研究材料的种类和行李空间 

接下来包含 N 行,每行两个整数 wi 和 vi,代表第 i 种研究材料的重量和价值

输出描述:

输出一个整数,表示最大价值。

输入示例:

4 5
1 2
2 4
3 4
4 5

输出示例:

10

 1.dp状态描述(与01背包相同)

dp[i][j]表示前i个物品中行李空间为j时能带的最大价值   

space[i]表示i物品所需空间

value[i]表示i物品的价值

2.递推公式

先遍历物品再遍历背包空间时
新来一个物品i时面对两种情况 带或不带,带的前提是当前空间>新物品空间I,带的话可以选择带n个,则带的结果是以dp[i][j-space[i]]+value[i]表示,因为此时只需要空间变小即可,依旧可以选择到第i个物品
if(j>=space[i]) dp[i][j]=max(dp[i][j-space[i]]+value[i],dp[i-1][j]);
else dp[i][j]=dp[i-1][j]

3. 初始状态

是从一个一个物品开始遍历,初始状态有第一个物品即可(第一行),也有01背包略有不同

    for(int i=0;i<=n;i++)
    {
       if(i>=space[0]) dp[0][i]=max(dp[0][i-space[0]]+value[0],value[0]);
    }

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int m = 0, n = 0;
    cin >> m >> n;
    vector<int> space,value;
    int tempM=m;
    while(tempM--)
    {
        int tempSpace,tempValue;
        cin>>tempSpace>>tempValue;
        space.push_back(tempSpace);
        value.push_back(tempValue);
    }

    vector<vector<int>> dp(m,vector<int>(n+1,0));
    // //初始状态第一行即可
    for(int i=0;i<=n;i++)
    {
        if(i>=space[0]) dp[0][i]=max(dp[0][i-space[0]]+value[0],value[0]);
    }
    for(int i=1;i<m;i++)
    {
        for(int j=1;j<=n;j++)
        {
            //与01背包唯一不同点就是选择带之后,依然可以选择继续带,则用dp[i][j-space[i]]+value[i]
            if(j>=space[i]) dp[i][j]=max(dp[i][j-space[i]]+value[i],dp[i-1][j]);
            else dp[i][j]=dp[i-1][j];
        }
    }
    cout<<dp[m-1][n];
    return 0;
}

三.一维数组解题

上述代码中都是按“一行”结束后进行下一行的值计算,且每次计算最多只间隔一行,没有出现间隔多行的情况,在计算第100行时只需要第99行,那么保存的0-98行都是浪费内存。

3.1 01背包

1.状态描述:

dp[j]表示空间为j时能装下的最大重量

2.递推公式:

if(j>=space[i]) dp[j]=max(dp[j-space[i]]+value[i],dp[j]);

3.初始状态
    for(int i=0;i<=n;i++)
    {
        if(i>=space[0]) dp[i]=value[0];
    }

4.遍历顺序

如果是正序:遍历物品i时

假设dp[j]已经装入了物品i,而后的dp[j+n]也可能装入物品i(可能dp[j-space[i]]的值已经变化了 不再是未装入物品i时的值)

举一个例子:物品0的重量weight[0] = 1,价值value[0] = 15

如果正序遍历

dp[1] = dp[1 - weight[0]] + value[0] = 15

dp[2] = dp[2 - weight[0]] + value[0] = 30

此时dp[2]装入了两次物品0

如果是倒序:则不会出现重复装入情况,因为dp[j-space[i]]未变化,未装入物品i

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int m = 0, n = 0;
    cin >> m >> n;
    vector<int> space,value;
    int tempM=m;
    while(tempM--)
    {
        int tempSpace;
        cin>>tempSpace;
        space.push_back(tempSpace);
    }
    tempM=m;
    while(tempM--)
    {
        int tempValue;
        cin>>tempValue;
        value.push_back(tempValue);
    }
    vector<int> dp(n+1,0);
    // //初始状态第一行即可
    for(int i=0;i<=n;i++)
    {
        if(i>=space[0]) dp[i]=value[0];
    }
    for(int i=1;i<m;i++)
    {
        for(int j=n;j>=space[i];j--)
        {
            dp[j]=max(dp[j-space[i]]+value[i],dp[j]);
        }
    }
    cout<<dp[n];
    return 0;
}

 3.2 完全背包

52. 携带研究材料(第七期模拟笔试) (kamacoder.com)

题目与01背包唯一不同点是,物品i可以带入多个

1.将01背包的遍历顺序改为正序

2.修改初始状态 dp[i]=max(dp[i-space[0]]+value[0],value[0]); 

#include <iostream>
#include <vector>
using namespace std;
int main() {
    int m = 0, n = 0;
    cin >> m >> n;
    vector<int> space,value;
    int tempM=m;
    while(tempM--)
    {
        int tempSpace,tempValue;
        cin>>tempSpace>>tempValue;
        space.push_back(tempSpace);
        value.push_back(tempValue);
    }
    vector<int> dp(n+1,0);
    for(int i=space[0];i<=n;i++)
    {
        dp[i]=max(dp[i-space[0]]+value[0],value[0]);
    }
    for(int i=1;i<m;i++)
    {
        for(int j=space[i];j<=n;j++)
        {
            dp[j]=max(dp[j-space[i]]+value[i],dp[j]);
        }
    }
    cout<<dp[n];
    return 0;
}

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

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

相关文章

OpenCascade源码剖析:Handle类

Handle其实就是智能指针的上古版本&#xff0c;了解一点C11的应该对shared_ptr非常熟悉&#xff0c;那么你就把Handle当做shared_ptr来理解就没有任何问题了。 不过OCCT的Handles是侵入式的实现&#xff0c;前面讲过Standard_Transient类提供了引用计数机制&#xff0c;这个就…

新质生产力助春播春管:佳格天地连续第5年上线大数据平台,服务春季生产

随着“惊蛰”节气过去,全国各地陆续掀起春播春管热潮。今年的政府工作报告中指出,2023年我国粮食产量1.39万亿斤,再创新高。2024年要坚持不懈抓好“三农”工作,扎实推进乡村全面振兴,粮食产量预期目标1.3万亿斤以上。 粮食产量预期目标的明确为一年农事生产指引了方向。同时,新…

地址分词 | EXCEL批量进行地址分词,标准化为十一级地址

一 需求 物流需要对用户输入地址进行检查&#xff0c;受用户录入习惯地址可能存在多种问题。 地址标准化是基于地址引擎和地址大数据模型&#xff0c;自动将地址信息标准化为省、市、区市县、街镇、小区、楼栋、单元、楼层、房屋、房间等元素&#xff0c;补充层级缺失数据、构建…

导出谷歌gemma模型为ONNX

参考代码如下&#xff08;从GitHub - luchangli03/export_llama_to_onnx: export llama to onnx修改而来&#xff0c;后面会合入进去&#xff09; 模型权重链接参考&#xff1a; https://huggingface.co/google/gemma-2b-it 可以对modeling_gemma.py进行一些修改(transforme…

LLCC68与SX1278 LoRa模块的优势对比?

LLCC68和SX1278都是Semtech公司推出的LoRa调制解调器模块&#xff0c;属于LoRa模块家族。它们在无线通信领域都有着广泛的应用&#xff0c;但具体的优势会取决于具体的应用场景和需求。下面是对LLCC68和SX1278 LoRa模块的一些优势对比&#xff1a; LLCC68 LoRa模块的优势&#…

qt自定义时间选择控件窗口

效果如图&#xff1a; 布局如图&#xff1a; 参考代码&#xff1a; //DateTimeSelectWidget #ifndef DATETIMESELECTWIDGET_H #define DATETIMESELECTWIDGET_H#include <QWidget> #include <QDateTime>namespace Ui { class DateTimeSelectWidget; }class DateTim…

【手游联运平台搭建】游戏平台的作用

随着科技的不断发展&#xff0c;游戏行业也在不断壮大&#xff0c;而游戏平台作为连接玩家与游戏的桥梁&#xff0c;发挥着越来越重要的作用。游戏平台不仅为玩家提供了便捷的游戏体验&#xff0c;还为游戏开发者提供了广阔的市场和推广渠道。本文将从多个方面探讨游戏平台的作…

扩展CArray类,增加Contain函数

CArray不包含查找类的函数&#xff0c;使用不便。考虑扩展CArray类&#xff0c;增加Contain函数&#xff0c;通过回调函数暴露数组元素的比较方法&#xff0c;由外部定义。该方法相对重载数组元素的“”符号更加灵活&#xff0c;可以根据需要配置不同的回调函数进行比较 //类型…

继深圳后,重庆与鸿蒙展开原生应用开发合作

截至2023年底&#xff0c;开源鸿蒙开源社区已有250多家生态伙伴加入&#xff0c;开源鸿蒙项目捐赠人达35家&#xff0c;通过开源鸿蒙兼容性测评的伙伴达173个&#xff0c;累计落地230余款商用设备&#xff0c;涵盖金融、教育、智能家居、交通、数字政府、工业、医疗等各领域。 …

底层day3作业

思维导图 作业&#xff1a;1.总结任务的调度算法&#xff0c;把实现代码再写一下 算法&#xff1a;抢占式调度时间片轮转 1.抢占式调度&#xff1a;任务优先级高的可以打断任务优先级低的执行&#xff08;适用于不同优先级&#xff09; 2.时间片轮转&#xff1a;每一个任务拥…

react的diff源码

react 的 render 阶段&#xff0c;其中 begin 时会调用 reconcileChildren 函数&#xff0c; reconcileChildren 中做的事情就是 react 知名的 diff 过程 diff 算法介绍 react 的每次更新&#xff0c;都会将新的 ReactElement 内容与旧的 fiber 树作对比&#xff0c;比较出它们…

电脑小问题:Windows更新后黑屏

Windows 更新后黑屏解决方法 在 Windows 更新后&#xff0c;伴随了一个小问题&#xff0c;电脑启动后出现了桌面黑屏。原因可能是火绒把 explorer.exe 当病毒处理了。 下面讲解 Windows 更新后黑屏的解决方法&#xff0c;步骤如下&#xff1a; 1. 按 ctrl alt delete 组合键…

基于Python3的数据结构与算法 - 12 数据结构(列表和栈)

目录 一、引入 二、分类 三、列表 1. C语言中数组的存储方式 2. Python中列表的存储方式 四、栈 1. 栈的应用 -- 括号匹配问题 一、引入 定义&#xff1a;数据结构是指相互之间存在着一种或多种关系的数据元素的集合和该集合中数据元素之间的关系组成。简单来说&#x…

portainer管理远程docker和docker-swarm集群

使用前请先安装docker和docker-compose&#xff0c;同时完成docker-swarm集群初始化 一、portainer-ce部署 部署portainer-ce实时管理本机docker&#xff0c;使用docker-compose一键拉起 docker-compose.yml version: 3 services:portainer:container_name: portainer#imag…

Docker上部署LPG(loki+promtail+grafana)踩坑复盘

Docker上部署LPG&#xff08;lokipromtailgrafana&#xff09;踩坑复盘 声明网上配置部署踩坑 声明 参考掘金文章&#xff1a;https://juejin.cn/post/7008424451704356872 版本高的用docker compose命令&#xff0c;版本低的用docker-compose 按照文章描述&#xff0c;主要准备…

UVA378 Intersecting Lines 题解

UVA378 Intersecting Lines 题解 怎么这么多点斜式邪教啊。 解法 在计算几何中&#xff0c;我们应该尽可能地避免使用浮点数的计算&#xff0c;尽可能地使用向量计算。 本篇题解默认读者具有向量基础。 为了方便讲解&#xff0c;我们将输入的四个点分别记作 A , B , C , …

本鲸多方位助力创业者高效对接创新创业机遇

在科技创新的浪潮中&#xff0c;创业者们不断探索着新的商业机会&#xff0c;寻求着创新创业的道路。然而&#xff0c;面对复杂多变的市场环境和激烈的竞争压力&#xff0c;如何高效对接创新创业机遇成为了摆在创业者面前的重要课题。 本鲸依托海南本鲸投资有限公司和重庆本鲸…

关于Vivado的实施过程、SDC和XDC约束支持、Vivado实施子流程、Tcl API支持脚本

关于Vivado的实施过程 AMD Vivado™设计套件可实现以下AMD设备体系结构&#xff1a;AMD Versal™自适应计算加速平台&#xff08;自适应SoC&#xff09;&#xff0c;AMDUltraScale™、AMD UltraScale™和AMD 7系列FPGA。各种设计来源如下支持&#xff0c;包括&#xff1a; •…

WebGPU vs. 像素流

在构建 Bzar 之前&#xff0c;我们讨论过我们的技术栈是基于在云上渲染内容的像素流&#xff0c;还是基于使用设备自身计算能力的本地渲染技术。 由于这种选择会极大地影响项目的成本、可扩展性和用户体验&#xff0c;因此在开始编写一行代码之前&#xff0c;从一开始就采取正确…

typeorm-入门

简述 typeorm是一个数据库orm框架&#xff0c;在nestjs官网中有提到&#xff0c;可以充分发挥利用typescript的特性&#xff0c;当然也支持js其中涉及的概念包括 DataSource 数据源&#xff0c;Connection 连接数据库Entity 实体&#xff0c;实体类映射数据库表Relation 关系…