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

server/2024/10/19 13:21:01/

        题目:有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/server/111430.html

相关文章

计算机视觉 第三章图像到图像的映射

3.1 单应性变换 单应性变换是将一个平面内的点映射到另一个平面内的二维投影变换。单应性变换可用于图像配准、图像纠正和纹理扭曲&#xff0c;以及创建全景图像。实际上&#xff0c;单应性变换&#xff0c;按照下面的方程映射二维中的点&#xff1a; 或 xHx 对点进行归一化和…

8种必备Selenium编写自动化用例的技巧

在开始自动化时&#xff0c;您可能会遇到各种可能包含在自动化代码中的方法&#xff0c;技术&#xff0c;框架和工具。有时&#xff0c;与提供更好的灵活性或解决问题的更好方法相比&#xff0c;这种多功能性导致代码更加复杂。在编写自动化代码时&#xff0c;重要的是我们能够…

ES6基础----Generator的使用

目录 Generator 是 ES6提出的解决异步编程的方案之一 1、Generator 和传统函数不一样&#xff0c;使用 * 表示 2、Generator 函数可以使用 yield 中途暂停函数 3、Generator&#xff08;生成器&#xff09; 函数的返回值是一个遍历器 &#xff0c;需要定义一个变量接收遍历…

MAC安装miniconda提示“文本编码Unicode(UTF-8)不适用”解决方案

需求背景 客户需要在mac环境下安装miniconda&#xff0c;提示安装失败&#xff0c;主要原因是安装版本不对&#xff0c;在选择合适版本&#xff0c;配置好环境后问题得以解决&#xff01; 报错提示 版本和环境错误 前往地址下载正确版本 https://repo.anaconda.com/miniconda…

DMDSC集群安装

1. 环境描述 机器情况&#xff1a; 存储情况&#xff1a; 2. 部署前准备 2.1. 目录规划和创建 创建和规划目录在2个节点都需要执行。 DSC环境搭建的目录&#xff1a;/dmdba/dmdbms DM执行码和工具存放于目录&#xff1a;/dmdba/dmdbms/bin 配置文件存放于目录&#xff1a…

在vue中,组件A如何调用组件B的方法

刚刚测试人员向我反馈&#xff0c;说这条提交记录审核之后&#xff0c;另一个页签的列表显示没有做状态的同步渲染。 我心想&#xff1a;竟还有这种荒唐事&#xff1f; 好了&#xff0c;废话不多说&#xff0c;直接上菜。这种问题&#xff0c;一眼前端问题&#xff08;我从前端…

百度:未来or现在 顾此失彼?

用AI押注未来&#xff0c;却丢了现在 国内AI先行者百度 走到哪了&#xff1f; 作为这个星球最热门的概念&#xff0c;AI无疑是个好故事&#xff0c;不只是百度&#xff0c;美股的一众科技公司几乎都在讲述自己的AI投入及发展成果&#xff0c;市值也随着AI预期坐过山车。而市场…

架构基础 -- Web框架之FastAPI

FastAPI&#xff1a;背景与使用案例介绍 FastAPI的背景 FastAPI是一个现代、快速&#xff08;高性能&#xff09;的Web框架&#xff0c;基于Python 3.7编写&#xff0c;利用Python的类型提示&#xff08;type hints&#xff09;来实现自动生成文档和高效的数据验证。由Sebast…