【OJ】动规练习七之【模板】01背包

个人主页 : zxctscl
如有转载请先通知

DP41 【模板】01背包

  • 1. DP41 【模板】01背包
  • 2. 分析
  • 3. 代码
  • 4. 优化
  • 5. 优化后代码

1. DP41 【模板】01背包

在这里插入图片描述

2. 分析

一、题目解析:
来看一下例1,3代表有三个物品,5代表能够容纳的体积。第一行要求中并没有说把背包全部装满,选择价值最大的就行,而第二行输出要求的是装满时候的价值。
在体积是5条件下,第一种可以选1号物品和3号物品,它们价值就是10+4=14;第二种可以选择2号和3号,它们价值就是5+4=9,第一行输出没有要求背包装满,所以选择第一种方式就行。
第二行输出是背包恰好装满的情况,就选择第二种情况。
在这里插入图片描述
而输出背包必须装满的情况可能是不存在的,就像例2:
给的三个物品体积凑不出来体积为8的情况。
在这里插入图片描述

二、算法原理:
(1)先来做第一行返回值:

  1. 状态表示
    以某一个位置为结尾
    如果用dp[i]来表示从前i个物品中选择,在所有选择中的最大价值,但是还得考虑体积的大小。所以这里的状态表示是:
    dp[i][j]:从从前i个物品中选择,总体积不超过j的所有选择中,能挑出来的最大价值。

  2. 状态转移方程
    根据最后一步的状况,分情况讨论。
    第一种情况:不选择i物品,那么就是在i-1里面选择,并且体积也依旧小于j,所以就是dp[i-1][j]
    在这里插入图片描述

第二种情况:选择i物品,那么必须有w[i],实现的价值最大,就得从i-1里面挑价值最大的出来,并且此时体积要改变,所以到这里的体积必须能够装下v[i],到i-1位置体积就必须小于j-v[i],所以这里的状态表示就是w[i]+dp[i-1][j-v[i]]
然后求这两种情况下的最大值就可以了。

  1. 初始化
    dp表从1开始计数,就多了一行和一列。要保证第一行和第一列填表正确,物品从0中选就是0,体积从0中挑还是0,所以初始化为0就行。

  2. 填表顺序
    它依赖它的上一行位置,i-1表示的是上一行,从上往下

  3. 返回值

返回dp[n][v]
(2)先来做第一行返回值:

  1. 状态表示
    只需要v的位置正好等于j就行
    dp[i][j]:从从前i个物品中选择,总体积正好等于j的所有选择中,能挑出来的最大价值。

  2. 状态转移方程
    第一种情况:不选择i物品,那么就是在i-1里面选择,并且体积也依旧小于j,所以就是dp[i-1][j],但是这里j可能凑不到总体积,就用一个dp[i][j]=-1来表示这样的情况,所以得先判断dp[i][j]是不是等于-1,所以这种情况就不选择。

第二种情况:选择i物品,那么必须有w[i],实现的价值最大,就得从i-1里面挑价值最大的出来,并且此时体积要改变,所以到这里的体积必须能够装下v[i],到i-1位置体积就必须小于j-v[i],但是这里必须判断dp[i][j]是不是等于-1,所以这里的状态表示就是dp[i][j]不是等于-1情况下w[i]+dp[i-1][j-v[i]]

  1. 初始化
    第一个位置没有物品直接物品和体积都是0,第一行[0,1]位置没有物品,想要凑成体积是1是不可能的,所以第一行剩下的位置就初始化为-1。第一列表示想要把体积正好凑成0,那么不选就是0,就初始化为0就行
    在这里插入图片描述

  2. 填表顺序
    从上往下

  3. 返回值
    先得判断一下dp[n][V]是不是等于-1,如果是就返回0,不是就返回dp[n][V]
    在这里插入图片描述

3. 代码

#include <cstring>
#include <iostream>

using namespace std;
const int N = 1010;
int n, V, v[N], w[N];
int dp[N][N];

int main() {
    cin >> n >> V;
    for (int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= V; j++) {
            dp[i][j] = dp[i - 1][j];
            if (j >= v[i])dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
            
        }
    }
    cout << dp[n][V] << endl;

    //第二问
    memset(dp, 0, sizeof dp);
    for (int j = 1; j <= V; j++)dp[0][j] = -1;


    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= V; j++) {
            dp[i][j] = dp[i - 1][j];
            if (j >= v[i]&&dp[i-1][j-v[i]]!=-1) {
                dp[i][j] = max(dp[i][j], dp[i - 1][j - v[i]] + w[i]);
            }
        }
    }
     cout <<(dp[n][V]==-1?0:dp[n][V]) << endl;
    
    return 0;
}
// 64 位输出请用 printf("%lld")

4. 优化

  1. 利用滚动数组做空间上的优化
  2. 代码在原基础上修改即可

在填第i行的时候,仅想要i-1行就可以。
就是说要填第1行的数据就需要第0行的数据,第1行填完之后,第0行就没有用了,需要这一行变得有用,就把这一行滚动到第2行,然后利用第1行的值来填第2行,以此类推,就可以更新完这个dp表。
在这里插入图片描述
所有这里只需要用到数组就只用到一维。

遍历顺序要改为从右往左。

在这里插入图片描述

5. 优化后代码

删除所有横坐标,遍历顺序从右往左

#include <cstring>
#include <iostream>

using namespace std;
const int N = 1010;
int n, V, v[N], w[N];
int dp[N];

int main() {
    cin >> n >> V;
    for (int i = 1; i <= n; i++)
        cin >> v[i] >> w[i];

    for (int i = 1; i <= n; i++) {
        for (int j = V; j >=v[i]; j--) 
             dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
    }
    cout << dp[V] << endl;

    //第二问
    memset(dp, 0, sizeof dp);
    for (int j = 1; j <= V; j++)dp[j] = -1;


    for (int i = 1; i <= n; i++) {
        for (int j = V; j >=v[i]; j--) 
           if(dp[j-v[i]]!=-1)
              dp[j] = max(dp[j], dp[j - v[i]] + w[i]);
    }
   
     cout <<(dp[V]==-1?0:dp[V]) << endl;
    
    return 0;
}
// 64 位输出请用 printf("%lld")

注意:

  1. 这些思路是可以套用到很多题目里面的。
  2. 不要去强行解释优化后代码的状态表示及状态表示方程。

有问题请指出,大家一起进步!!!

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

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

相关文章

VGA 多分辨率

REVIEW VGA 时序与实现-CSDN博客 对于不同分辨率&#xff0c;每次使用都去查表比较麻烦&#xff1b; 学习条件编译的使用&#xff0c;减轻后续调用的麻烦。 1. 条件编译格式 条件编译是当设计中满足某个条件时&#xff0c;将该条件下的一段代码编译进设计中。 因此&#xff0…

C++ 类和对象(初篇)

类的引入 C语言中&#xff0c;结构体中只能定义变量&#xff0c;在C中&#xff0c;结构体内不仅可以定义变量&#xff0c;也可以定义函数。 而为了区分C和C我们将结构体重新命名成class去定义 类的定义 标准格式&#xff1a; class className {// 类体&#xff1a;由成员函…

AI绘图:Stable Diffusion ComfyUI局部重绘与智能扩图全面教程

前言 在数字艺术创作中&#xff0c;局部重绘和智能扩图是两个非常重要的功能。局部重绘允许我们在保留原有图像的基础上&#xff0c;对特定区域进行修改或创新。而智能扩图则能够帮助我们在图像的边缘添加新的元素&#xff0c;从而扩展图像的内容。本文将详细介绍如何在Stable…

深度学习pytorch好用网站分享

深度学习在线实验室Featurizehttps://featurize.cn/而且这个网站里面还有一些学习教程 免费好用 如何使用 PyTorch 进行图像分类https://featurize.cn/notebooks/5a36fa40-490e-4664-bf98-aa5ad7b2fc2f

jforgame-doctor快速入门

背景 游戏热更新,是指在不重启服务器/客户端app的情况下,对游戏内容进行修改或者对代码bug进行修复。 对于一个上线产品项目来说,热更新为维持项目的稳定健康提供了坚强的保障。小到策划数据的修改,代码bug的修改,大到动态扩展游戏业务功能。试想一下,没有热更新机制,…

基于SSM的邮票鉴赏系统(有报告)。Javaee项目。ssm项目。

演示视频&#xff1a; 基于SSM的邮票鉴赏系统&#xff08;有报告&#xff09;。Javaee项目。ssm项目。 项目介绍&#xff1a; 采用M&#xff08;model&#xff09;V&#xff08;view&#xff09;C&#xff08;controller&#xff09;三层体系结构&#xff0c;通过Spring Spri…

电脑硬盘分区表的两种格式:MBR 和 GPT

电脑硬盘分区表的两种格式&#xff1a;MBR 和 GPT 段子手168 2024-4-5 电脑硬盘分区表有两种格式&#xff1a;MBR 和 GPT&#xff1a; 一、MBR 分区表 1.MBR 是主引导记录 (Master Boot Record) 的英文缩写 在传统&#xff08;Legacy&#xff09;硬盘分区模式中&#xff0c…

1970-2021年全国区县级碳排放数据8

1970-2021年全国区县级碳排放数据 1、时间&#xff1a;1970-2021年 2、指标&#xff1a;2877个区县 3、来源&#xff1a;EDGAR 4、指标&#xff1a;二氧化碳排放量 5、样本量&#xff1a;14W 6、指标解释&#xff1a; 二氧化碳排放是一个生态环境专业术语&#xff0c;主…

项目经理必须知道的三大财务报表相关知识

清晖有个不错的讲项目经理应该知道的三大财务报表相关知识&#xff0c;地址&#xff1a;项目经理必备的财务知识_哔哩哔哩_bilibili

深度学习的数学基础--Homework2

学习资料&#xff1a;https://www.bilibili.com/video/BV1mg4y187qv/?spm_id_from333.788.recommend_more_video.1&vd_sourced6b1de7f052664abab680fc242ef9bc1 神经网络的特点&#xff1a;它不是一个解析模型&#xff0c;它的储存在一堆参数里面&#xff08;确定一个超平…

File(一),IO流,递归详解

File类 介绍 java.io.File类是Java语言提供了用来描述文件和目录(文件夹)的 构造 方法 注意&#xff1a; 构造方法中通常用的是第一个方法文件和目录可以通过File封装成对象File封装的对象仅仅是一个路径名&#xff0c;它是可以存在的&#xff0c;也可以不存在 绝对路径…

详解protected访问限定符

1.同一个包中的同一类 package demo1;public class Test1 {protected int a 10;protected void b() {System.out.println("这是protected修饰的成员方法");}public static void main(String[] args) {Test1 test new Test1();System.out.println(test.a);test.b()…

Vue学习笔记-S1

1 什么是Vue Vue是一款用于构建用户界面的渐进式JavaScripte框架&#xff0c;可基于数据渲染用户页面. 1.1 Vue的知识架构 Vue核心包&#xff1a;声明式渲染、组件系统Vue构建&#xff1a;客户端路由、状态管理、构建工具局部使用Vue&#xff1a;快速入门、常用指令、生命周…

4.5日学习打卡----学习Apache HttpClient 5

4.5日学习打卡 目录&#xff1a; 4.5日学习打卡Apache Commons HttpClient简介 Apache HttpClient 5简介依赖HttpClient 5 GET 请求HttpClient 5 Fluent GETHttpClient5 GET 请求参数HttpClient 5 POST 请求HttpClient 5 Fluent POSTHttpClient5 POST JSON 参数HttpClient 5 设…

什么是地理信息系统(GIS),它能为我们做什么?

当您准备从事GIS相关职业或准备建设一个GIS相关的系统时&#xff0c;您需要对GIS有一个大概的整体了解。这篇文章很适合您从宏观了解GIS当前的整体情况及发状况&#xff01;希望这篇文章对您有所帮助&#xff01; 什么是地理信息系统&#xff1f; GIS 代表地理信息系统。…

linux时间同步工具chrony的配置和时间设置的相关说明

目录 目录 介绍 1.搭建ntp服务器 2.配置ntp客户端 3.其他设置 4.客户端无法进行时间同步 介绍 目前比较流行的时间同步工具有ntpd和chrony&#xff0c;ntpd采用123/UDP端口通信&#xff0c;chrony采用323/UDP端口通信。Centos7以上版本默认安装chrony服务来同步时间&#x…

go | 上传文件 | tcpdumpwireshark 抓包分析

go 上传文件 package mainimport ("fmt""log""github.com/gin-gonic/gin" )/*执行命令&#xff1a; curl -X POST http://localhost:8080/upload -F "file/path/main.zip" -H "Content-Type:multipart/form-data"*/ func m…

Python实战 | 如何使用 Python 调用 API

本文目录 一、前言 二、调用浙江数据开放平台API获取数据 &#xff08;一&#xff09;API获取数据的流程 &#xff08;二&#xff09;HTTP请求 &#xff08;三&#xff09;API的参数 &#xff08;四&#xff09;使用request库获取API数据 三、调用百度通用翻译API 四、总结 本文…

vscode-task.json自定义任务

以下所有内容,参考自VScode官方文档: vscode_task-docs任务说明文档vscode_variables-reference-docs变量说明文档vscode addtional docs for task 说明: 博客内容均为个人理解,有错误请移步官方文档, 查阅文档, 纠正错误. 这篇blog记录一下个人对vscode任务(task)的使用方法 个…

C++中的STL——vector类的基本使用

目录 vector介绍 vetor类定义 vector常见构造 vector类中的容量操作 size()函数与capacity()函数 resize()函数 reserve()函数 max_size()函数 vector类中的数据遍历操作 operator[]()与at()函数 vector类中的迭代器遍历 正向遍历begin()和end()迭代器——非const …