动态规划---01背包问题理论总结

news/2024/12/22 22:03:23/

        题目:有n件物品和一个最多能背重量为w的背包。第i件物品的重量时weight[i],得到的价值是value[i]。每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大。

解法一:dp二维数组

1.dp数组的含义

        dp[i][j]表示将下标为(0,i)的物品任取,装入到最大容量为j的背包中,价值总和最大为多少。

2.dp数组的递推公式

        物品i不放入容量为j的背包中可以用dp[i-1][j]表示。

        物品i想要放入容量为j的背包中时,背包里至少要剩余容量weight[i]才可以,放入后背包中的价值总和为dp[i][j-weight[i]]+value[i]。

        所以dp[i][j]=max( dp[i-1] [j] , dp[i-1] [ j-weight[i] ]+value[i] )

3.dp数组初始化

        如果背包容量j为0,那么哪个物品都无法装入,所以dp[i][0]=0

        由第二步得出的递推公式可知,i是由i-1推导出来的,那么i=0时一定要初始化。dp[0][j]代表着把下标为0的物品装入到容量为j的背包中的最大价值。当j<weight[0]时,dp[0][j]=0,当j>=weight[0]时,dp[0][j]=value[0]。

        其他下标的初始值是什么都可以,因为后面都会被覆盖掉,经常会选择把它们都初始化为0

4.遍历顺序

        dp数组是一个二维数组,有两个遍历维度:物品,背包重量(容量)。

        结论是:先遍历物品也可以,先遍历背包重量也可以。正序遍历倒序遍历也都可以。一般都选择先正序遍历物品,再正序遍历背包重量。

        为什么都可以呢?观察递推公式,dp[i][j]是靠i-1那一行的数据推导出来的,先遍历物品后遍历背包重量的情况下计算i行时i-1行已经计算过了,先遍历背包重量后遍历物品的情况下dp[i-1] [j],dp[i-1] [ j-weight[i] ]都已经计算过了。

解法二:dp一维数组(滚动数组)

1.dp数组的含义

        二维数组把i-1层的数据拷贝到i层,递推公式就可以写成

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

        此时完全可以使用只保留j,使用一维数组表示该递推公式

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

dp[j]代表容量为j的背包,所背的物品价值最大可以是多少。

2.dp数组的递推公式

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

3.dp数组初始化

        根据递归公式,dp数组在推导的时候一定是取价值最大的数。

        如果题目给的价值都是正整数,那么非0下标都初始化为0就可以了。

        如果题目给的价值有负数,则将非0下标初始化为负无穷。

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

4.遍历顺序

        外层for循环遍历物品(正序),内层for循环遍历背包重量(倒序)。

        内层倒序保证了每个物品只放了一次,但如果正序遍历,那么一个物品会被重复多次加入。        

        举例说明:物品0的重量weight[0]=1,价值value[0]=15。

        如果正序遍历,dp[1]=dp[1-weight[0]]+value[0]=15,

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

                               物品0被加入了两次!

        如果倒序遍历,dp[2]=dp[2-weight[0]]+value[0]=0+15=15

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

        问:为什么二维dp不用倒序,一维dp就要倒序呢?

        答:二维dp中计算dp[i][j]使用的一直是i-1行的数据,没有受到i行数据的影响,而一维dp中计算i行的dp[j]初始化是i-1行数据,但在推导的过程中会逐渐覆盖掉i-1行的值,计算时会受到i行数据的干扰。

        问:为什么不能先遍历背包重量,再遍历物品呢?

        答:因为一维dp的写法,背包容量一定是要倒序遍历,如果遍历背包容量放在外层,那么每个dp[j]只能放入一个物品,即:背包里只放了一个物品。


http://www.ppmy.cn/news/1520381.html

相关文章

档案|基于SprinBoot+vue的档案管理系统(源码+数据库+文档)

档案管理系统 基于SprinBootvue的档案管理系统 一、前言 二、系统设计 三、系统功能设计 管理员功能模块实现 学生功能模块实现 四、数据库设计 五、核心代码 六、论文参考 七、最新计算机毕设选题推荐 八、源码获取&#xff1a; 博主介绍&#xff1a;✌️大厂码农…

【日常记录-Linux】.tar.xz、.tar.bz2、tar.gz解压

Author&#xff1a;赵志乾 Date&#xff1a;2024-08-30 Declaration&#xff1a;All Right Reserved&#xff01;&#xff01;&#xff01; 1. 简介 Linux平台下&#xff0c;常见.tar.xz、.tar.bz2、.tar.gz等类型的压缩包。 2. 解压缩说明 2.1 .tar.xz解压缩 .tar.xz压缩包表…

OpenCV 深拷贝与浅拷贝的区别

目录 一、概述 1.1原理 1.2区别 1.3应用 二、代码 2.1浅拷贝代码 2.2深拷贝代码 OpenCV图像处理与应用实战算法汇总地址&#xff1a; OpenCV 图像处理应用实战算法列表汇总&#xff08;长期更新&#xff09; 一、概述 在 OpenCV 和 NumPy 中&#xff0c;深拷贝和浅拷贝…

React 实现PDF预览(数据源使用文件流而不是url)

一 前提 应公司要求&#xff0c;需要进行上传文件&#xff08;pdf&#xff09;的预览功能&#xff0c;网上大部分都是使用url作为预览数据源&#xff0c;但是现在后端那边只返回了pdf文件流&#xff0c;所以本文主要是用文件流来预览pdf。 二 首先需要获取pdf文件流&#xff…

【Elasticsearch】file-beat 将文件数据导入es

1、备份 filebeat.yml 文件&#xff1a; 2、新 filebeat.yml 文件配置示例&#xff1a; ###################### Filebeat Configuration Example ########################## Filebeat inputs filebeat.inputs: - type: logenabled: true # 注意&#xff1a;# 文件最后必须…

cenos 7 安装 golang

1、下载地址 All releases - The Go Programming Languagehttps://golang.google.cn/dl/ 2、解压 tar -C /usr/local -zxf go1.14.3.linux-amd64.tar.gz 3、配置PATH 文件 /etc/profile&#xff08;全局&#xff09; 或 $HOME/.profile&#xff08;用户&#xff09; 或 ~/…

基于人工智能的智能客服系统

目录 引言项目背景 客服系统的现状与挑战AI在客服领域的应用前景系统设计 系统架构模块划分关键技术与实现 自然语言处理&#xff08;NLP&#xff09;对话管理语音识别与合成情感分析数据准备与训练 数据收集数据预处理模型训练系统集成与部署 前端接口设计后端服务实现系统集…

基于人工智能的新闻文本自动分类系统

目录 引言项目背景环境准备 硬件要求软件安装与配置系统设计 系统架构关键技术代码示例 数据预处理模型训练模型预测应用场景结论 1. 引言 新闻文本分类是自然语言处理中的一个经典任务&#xff0c;用于将新闻文本自动分类到不同的类别中&#xff0c;如体育、政治、科技等。…