3.8 动态规划 背包问题

一.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.mfbz.cn/a/441224.html

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

相关文章

使用docker安装运行rabbitmq---阿里云服务器

目录 0、阿里云没开端口的得要去安全组规则去添加&#xff1a; 1、下载RabbitMQ镜像&#xff1a; 2、查看镜像是否下载成功&#xff0c;得到docker镜像id&#xff1a; 3、运行RabbitMQ: 4、查看RabbbitMQ容器是否启动成功&#xff1a; 5、启动RabbitMQ中的插件管理 6、访…

RabbitMQ的web控制端介绍

2.1 web管理界面介绍 connections&#xff1a;无论生产者还是消费者&#xff0c;都需要与RabbitMQ建立连接后才可以完成消息的生产和消费&#xff0c;在这里可以查看连接情况channels&#xff1a;通道&#xff0c;建立连接后&#xff0c;会形成通道&#xff0c;消息的投递、获取…

Z Potentials | 星爵,他的征途不止向量数据库

纵观过去几十年的科技发展史&#xff0c;每一代新的技术架构的出现往往都伴随着新的数据范式的出现&#xff0c;也催生了多家百亿到千亿美金数据平台的诞生。如果说 2023 年科技领域的关键词是 LLM&#xff0c;那么数据库领域的关键词一定非向量数据库莫属。向量数据库是一种专…

C++面向对象程序设计-北京大学-郭炜【课程笔记(五)】

C面向对象程序设计-北京大学-郭炜【课程笔记&#xff08;五&#xff09;】 1、常量对象、常量成员函数1.1、常量对象1.2、常量成员函数1.3、常引用 2、友元&#xff08;friends&#xff09;2.1、友元函数2.2、友元类 3、运算符重载的基本概念3.1、运算符重载 4、赋值运算符的重…

红黑树的学习

红黑树 红黑树出自一种平衡的二叉查找树&#xff0c;是计算机科学中中用到的一种数据结构 1972年出现&#xff0c;当时被称之为平衡二叉B树。后来&#xff0c;1978年被修改为如今的红黑树 他是一种特殊的二叉查找树&#xff0c;红黑树的每一个节点上都有存储表示节点的颜色 …

HarmonyOS NEXT应用开发案例——自定义TabBar

介绍 本示例主要介绍了TabBar中间页面如何实现有一圈圆弧外轮廓以及TabBar页签被点击之后会改变图标显示&#xff0c;并有一小段动画效果。 效果图预览 使用说明&#xff1a; 依次点击tabBar页面&#xff0c;除了社区图标之外&#xff0c;其它图标往上移动一小段距离。 实现…

软件测试【测试用例设计】面试题详解

前言 今天笔者想和大家来聊聊测试用例&#xff0c;这篇文章主要是想要写给测试小伙伴们的&#xff0c;因为我发现还是有很多小伙伴在遇到写测试用例的时候无从下手&#xff0c;我就想和大家简单的聊聊&#xff0c;这篇文章主要是针对功能测试的。 一、微信功能测试 1.点击点…

STL之map容器代码详解

基础概念 简介&#xff1a; map中所有元素都是pair。pair中第一个元素为key&#xff08;键值&#xff09;&#xff0c;起到索引作用&#xff0c;第二个元素为value&#xff08;实值&#xff09;。所有元素都会根据元素的键值自动排序。 本质&#xff1a; map/multimap属于关…

【Android取证篇】渗透测试工具apk2url快速提取APK内的IP和URL地址

【Android取证篇】渗透测试工具apk2url快速提取APK内的IP和URL地址 通过渗透测试工具apk2url快速检索APK开发过程中没有删掉的URL地址&#xff0c;来发现一些搜索引擎、子域名查找不到的资源&#xff0c;从而进一步收集信息查找后台等—【蘇小沐】 1、实验环境 系统环境Wind…

Spring基础

spring讲义 spring官网 下文中所有项目都是通过 maven 构建的quickstart项目 csdn比较好的博客 1.什么是Spring框架 它是一个容器&#xff0c;帮助解决企业开发的难度&#xff0c;减轻对项目模块之间的管理&#xff0c;类和类之间的管理&#xff0c;帮助开发人员创建对象&a…

Linux——进程间通信

目录 进程间通信介绍 什么是进程间通信 为什么要进行进程间通信 怎么做到进程间通信 管道 管道的原理 匿名管道 pipe函数 简单线程池 管道读写的规则 命名管道 创建一个管道文件 在代码中创建管道 在代码中删除管道 命名管道实现serve与client通信 system V共享…

数组连续和 - 华为OD统一考试(C卷)

OD统一考试&#xff08;C卷&#xff09; 分值&#xff1a; 100分 题解&#xff1a; Java / Python / C 题目描述 给定一个含有N个正整数的数组&#xff0c;求出有多少连续区间&#xff08;包括单个正整数&#xff09;&#xff0c;它们的和大于等于 x。 输入描述 第一行为两个…

掌握Python操作Word:从基础到高级全覆盖

掌握Python操作Word&#xff1a;从基础到高级全覆盖 引言Python操作Word的基础文档的创建与打开文档的基本操作 创建和打开Word文档创建新的Word文档打开现有文档读取文档内容修改现有文档 编辑文档内容添加和编辑文本设置格式插入标题 处理文档结构操作段落列表的处理表格的操…

董宇辉所有商标已转到与辉同行名下!

近日董宇辉此前由东方优选申请的所有商标已转到与辉同行主体名下&#xff0c;普推知产老杨经检索发现&#xff0c;这些商标都是2022年6月由东方优选提交申请&#xff0c;在2023年12月28时提交商标转让&#xff0c;最近转让成功&#xff0c;转让周期是2个半月左右。 转让的商标除…

Windows11下载、安装和配置JDK(包含多个版本的JDK配置)

下载JDK17 下载地址 JDK_DOWNLOAD选择JDK17版本 安装JDK17 双击打开安装包 -> 选择下一步 -> 选择安装路径&#xff08;注意不要安装在带有中文的路径下&#xff09;->修改完路径后点击下一步->安装完成。 检验安装是否成功&#xff0c;打开cmd&#xff0c;输…

C#中实现接口的一些小知识(C#用abstract或virtual来实现接口成员)

文章目录 不可用的修饰可用的修饰非抽象类实现接口抽象类实现接口抽象类与接口方法同名时一同实现 不可用的修饰 在C#中实现接口时&#xff0c;我们不能直接使用static或const来实现接口成员&#xff0c;因为接口中的成员默认都是实例成员&#xff0c;并且它们表示一种契约&am…

每日学习总结20240308

每日总结 20240305 常用控件 QPushButton&#xff08;按钮&#xff09;&#xff1a;用于触发操作或响应用户点击事件。QLabel&#xff08;标签&#xff09;&#xff1a;用于显示文本或图像。QLineEdit&#xff08;行编辑器&#xff09;&#xff1a;单行文本输入框&#xff0…

Python学习笔记-Flask实现简单的抽奖程序(增加图片显示)

1.创建static文件夹,存放图片文件 2.hero列表数据更改为要抽奖的图片名 3.html中可以编写python语句,遍历hero列表内容渲染到表格中 4.在点击随机抽取后,可以获得名称,然后使用img标签,将获取的名称拼接到路径中 3.初始页面,访问127.0.0.1:5000/index 4.点击随机抽取后 5.py…

方阵的特征值与特征向量

目录 特征值 & 特征向量 相关性质 特征值 & 特征向量 相关性质

java(框架) springboot-1 基础使用+mybaits使用

学习视频&#xff1a;b站黑马java教程 tomcat spring-boot工程内嵌了tomcat服务器 所有请求经过DispatcherServlet(实现servlet接口的类)(核心控制器/前端控制器)处理&#xff0c;再通过DispatcherServlet转发给各个controller。 最后通过DispatcherServlet给浏览器响应数据…