首页 > 其他分享 >背包问题(0-1)学习心得

背包问题(0-1)学习心得

时间:2024-03-15 14:30:04浏览次数:38  
标签:遍历 weight 学习心得 问题 背包 数组 物品 dp

首先声明本文章为本人学习心得体会,仅供个人总结使用。如有错误,欢迎大家指正。

背包问题(0-1)


有a个物体和容量为b的背包,每个物体有对应的重量与价值,当背包装满时,最大价值为多少?

二维数组解法
  1. 确定二维数组含义

    • 二维数组dp的含义:0-i个物品任选放进容量为j的背包的最大价值
    • i就代表0-i个物品任意选
    • j则代表背包的容量
  2. 确定递推公式(即如何通过上一个位置的值得到下一个位置的值)

    • dp数组有两种状态,一个是放第i个物品得到其价值,另一个则是背包容量不够,不放第i个物品
		dp[i][j] = dp[i-1][j]; // 不放物品i
		dp[i][j] = dp[i-1][j - weight[i]] + value[i];// 放物品i

		// 递推公式
		dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
  1. 数组如何初始化

    • dp[][0]当背包容量为0时候什么东西都放不下,所以这一列肯定都初始化为0
    • dp[0][]当物品0存放时,如果容量小于物品0的重量则肯定为0,容量大于等于物品0的重量则都为物品0的价值
    • 其余位置就随便初始化了,不过为了方便起见,个人认为统一初始化为0比较好
  2. 遍历顺序

    • 先遍历物品或者是先遍历背包都可以,但是二者在数组中移动的方向不太一样
// 先遍历物品
// weight数组的大小就是物品个数,当然用value数组也可以
// 因为dp[0][0]已经初始化过了,所以直接从1开始
for(int i = 1; i < weight.size(); i++) { // 遍历物品
    for(int j = 1; j <= bagweight; j++) { // 遍历背包容量
        if (j < weight[i]){
	        dp[i][j] = dp[i - 1][j];
        } 
        else{
	        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
        } 
    }
}

// 先遍历背包
for(int j = 1; j <= bagweight; j++) { // 遍历背包容量
    for(int i = 1; i < weight.size(); i++) { // 遍历物品
        if (j < weight[i]){
	        dp[i][j] = dp[i - 1][j];
        }
        else{
	        dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - weight[i]] + value[i]);
        } 
    }
}
一维数组解法

其实一维数组的解法和二维数组的解法本质上是相同的,因为二维数组其实就是由多个一维数组组成,我们用二维数组解决这个问题的时候是由上一个状态推导而来,而一维数组只不过就是上一个状态和下一个状态的值会放在同一个位置上。

  • dp数组含义:容量为j的背包,所背的物品价值可以最大为dp[j]
  • 推导公式:因为变成了一维数组,所以推导公式就变为了
	dp[j] = max(dp[j], dp[j - weight[i]] + value[i]);
  • 初始化:其实初始化还是一样的,我们把整个一维数组初始化过后就可以进行相应的推导了(因为初始化后的值就相当于是上一状态)
  • 遍历顺序:一维数组的方式就只能先遍历物品再遍历背包,且必须倒序遍历。因为正序遍历可能会存在一个物品被放入多次。

最后希望本文章能够让你有所收获~

标签:遍历,weight,学习心得,问题,背包,数组,物品,dp
From: https://blog.csdn.net/weixin_74952982/article/details/136713044

相关文章

  • Qt opengl和qlabel的update同时更新,内存泄漏问题
    工作要做一个类似播放器的软件,但是需要自己解码,然后可能多张图像合成再显示,所以不能直接用QT播放视频的模块,就用了QOpenGLWidget来渲染。后面发现内存一直在涨,一直以为是自己的原因,因为解码分配的内存挺多的,折腾了快一个月了,后面发现是update频繁更新导致;如下代码,XVideoWidget继......
  • php多进程引发mysql查询问题
    1、报错:Packetsoutoforder.Expected1received56.Packetsize=3159346开始配置my.cnf的max_allowed_packet=2G可是没什么卵用原因:个人判断是因在laravelmysql的连接是随着php销毁而销毁;所以会保持数据库的连接会话能重复使用所以要配置database.php  配置文件opt......
  • c/c++数据对齐问题
    c/c++如何在栈上保证数据对齐:#include<iostream>struct__attribute__((aligned(16)))X{}; intmain(){Xx{};std::cout<<((longlong)&x)%16;}汇编代码X86-64(仅开头部分):main:pushrbpmovrbp,rspsubrsp,16可以看到并没有做什么特别操作,仅仅准备......
  • Gateway过滤器中调用OpenFeign时出现循环依赖问题
    为了保证JWT随机生成的密钥一致,我设计了一个token服务,专门获取JWT,和生成token。在网关使用client调用服务时,出现了bean循环依赖Thedependenciesofsomeofthebeansintheapplicationcontextformacycle:┌─────┐|gateWayGlobalFilterdefinedinfile[C:\Us......
  • 【已解决】Mybatis-plus中@TableLogic注解失效问题
    逻辑删除逻辑删除是指通过修改数据的状态或添加额外字段来表示数据的删除状态,而不是直接从数据库中物理删除数据记录。通常,会在数据库表中新增一个字段(如deleted),用来标识数据是否被删除。MyBatisPlus中实现逻辑删除在使用MyBatisPlus进行数据库操作时,实现逻辑删除......
  • STM32CubeMX没有生成Keil工程问题
    1. Project中选择IDE为MDK-ARM 2.你可能没有联网,所以在GENERATECODE时没有弹窗提示需要下载stm32cube_fw_XXX.zip软件包,根据提示登录(没有账号就注册一个)后按提示下载对应软件包即可,下图为下载中的stm32F4xx软件包。  安装后,重新GENERATECODE,即可生成MDK-ARM目录......
  • 关于mcu不适用ide,使用交叉编译工具开发的问题
    背景本文以ti的msp430系列单片机为例首先去官网下载交叉编译链https://www.ti.com.cn/tool/cn/MSP430-GCC-OPENSOURCE我们这里用windows做测试,下载windwos的就可以安装以后参照这个https://zhuanlan.zhihu.com/p/356963477......
  • 常见问题解决 --- idea与maven使用常识
    1.拿到项目代码后先要知道使用了哪些技术和工具。比如使用的是idea、eclipse还是maven创建的项目,使用什么编程语言,使用什么项目目录结构等等2.如何用maven创建的项目必然有pom.xml,每次修改pom文件后必须重新加载。3.如果修改代码后还是报错,尝试使用clean清除编译缓存再同步maven......
  • eclipse 问题之一:Plugin execution not covered by lifecycle configuration
    1、问题eclipse作为java工程的开发工具,可以集成maven直接管理maven工程。但是对于maven工程中描述的插件,有时候eclipse会报如下错误(示例:Pluginexecutionnotcoveredbylifecycleconfiguration:org.codehaus.mojo:exec-maven-plugin:3.1.1:java(execution:default......
  • 盘点一个Pandas实战需求的问题
    大家好,我是Python进阶者。一、前言前几天在Python最强王者交流群【wen】问了一个Pandas解决实际需求的实战问题。问题如下:请教:代码的目的为自动填充产品名字,有多个销售数据的表格,如例子,销售数据表格中的的产品名字一列为空,我把销售数据表格与产品信息表格进行根据产品IP进行合......