动态规划之经典案例《0-1背包问题》详解

动态规划之0-1背包问题(详解+分析+原码) 本篇文章将介绍算法专题之动态规划中的背包问题,更准确的说是背包问题中最简单的一种类型,即0-1背包问题,就是给你一定容量的背包和若干物品,每种物品只能选一次,告诉你每件物品的价值和体积,求背包里面物品的最大总价值。 阅读详情

0-1背包问题描述

有一个可装重量为w的背包和n件物品,每件物品都有重量和价值两个属性,且每件物品只有一件,只能选择装入或者不装,能装入的最大物品价值是多少?

一、贪心算法分析

看到求最值问题,一般是使用动态规划来解。为什么不使用贪心算法来解?因为贪心算法求的是局部最优解,而动态规划才能求得全局最优解。

举个例子:

现在有以下物品重量和价值数组W、V,背包最多装入9kg物品。
W = [4,6,5,2]
V = [7,8,5,3]

使用贪心算法时,每一步要做的就是对于第i件物品,我取还是不取,且只能抉择一次。这就需要使用一个标准来衡量后,进行决策。

  • 若使用价值重量比(v/w)作为贪心算法的决策方向,则贪心算法的每一步都选择重量轻价值高的物品。4件物品的价值重量比为:1.75、1.3、1、1.5,这样依次会选择第1件、第4件,总价值为10,重量为6,剩余3kg已不能再装入物品。但若选择第2件和第4件,总重量8,总价值为11,这又是更好地选择。若选择第1件和第3件,总重量9,总价值12,这又是更好的选择。所以,若单纯以价值重量比作为贪心的决策方向,是不能求得全局最优解的。
  • 如果决策标准是价值最高的物品呢?即先选第2件,再选第4件,总重量8,总价值11。那又能找到更好地选择:先选第1件,再选第3件,这样总重量9,总价值12。

所以总而言之,贪心算法只能求得一个差强人意的结果,但不是最好的结果。

二、动态规划分析

案例:

现在有m件物品,重量和价值表示为W、V数组,背包中最多装入n(kg)物品。输入m=3,n=4。
W = [2,1,3]
V = [4,2,3]

如果用动态规划解决背包问题需要怎样考虑呢?它不像贪心算法一样,对于第i件物品,选择取还是不取,且只能抉择一次。而是面对前i件物品,在背包容量为j的情况下,第i件物品我要不要取。动态规划需要枚举只看前i(0 ≤ i ≤ n)件物品,背包容量为j(0 ≤ j ≤ w)时所有的物品排列组合的情况,然后将在当时情况下能获取到的最大的价值记录下来。由此,动态规划数组需要保存什么值就显而易见了,见下。

1.动态规划需要考虑的三要素

  • 动态规划数组的意义:这里要考虑到两个状态:需要在前几件物品(i)中进行抉择和背包容量(j)。所以需要定义一个二维数组dp[i][j],表示为:在只考虑前i件物品的情况下,当背包容量为j时,枚举所有的物品排列组合情况获得的价值,记录最大价值。

  • 动态规划的初始值:当i=0时,表示只在前0件物品中做选择,也就是一件物品都不考虑,这种情况下不管背包容量为多少,能装的最大价值都是0;当j=0时,表示背包容量为0,这种情况下不管考虑前几件物品,都不能将其装入背包,即能装的最大价值也是0。

  • 状态转移方程:这里是最难考虑的。在只考虑前i件物品的情况下,是否取第i件物品怎么决策呢?现在定义第i件物品的重量为w[i],价值为v[i]。

    (1)若当前背包的总空间j不能容纳第i件物品,就不能将第i件物品放入背包,此时背包内最大价值就应该等于前i-1件物品的总价值,即dp[i - 1][j],那么就去前面查一下已经计算出的dp[i - 1][j]是多少,即dp[i][j] = dp[i - 1][j]。

    (2)若当前背包总空间j能容纳第i件物品,那就需要考虑一个问题:虽然当前背包能装下第i件物品,我一定要把它装进去吗?当然是不一定,如果这样考虑就变成了贪心算法(很容易理解)。因为第i件物品装进去虽然会增大背包的总价值,但同时也减少了背包的可用容量,可以这样理解:之前已经从前i-1件物品中选择了一部分放入了背包,如果此时放入第i件物品,就可能(并不是一定)需要从背包中已经放入的物品中再取出一部分,这样其实是增大背包总价值的同时也减少了总价值。所以需要先衡量第i件物品放进去和不放进去哪个总价值更大。分为以下<1>、<2>情况考虑:

    <1>将其放入背包,此时背包内就已经用掉了w[i]的容量,且最少有v[i]的价值了,那么剩余j - w[i]的容量最多能装多少价值的物品呢?就需要去查查已经计算出的只考虑前i-1件物品时能装的最大价值dp[i - 1][j - w[i]]是多少,这样算完后总价值就表示为dp[i][j] = dp[i - 1][j - w[i]] + v[i]。(第i件物品的重量w[i] = W[j-1],第i件物品的价值v[i] = V[i-1],因为在题设中给的代表物品重量和价值的W、V数组是从0开始索引的,因为现在只是理思路,暂时用小写的w[i]和v[i]来标记,等写代码时再替换为大写的W和V。)

    <2>不将其放入背包,此时背包内总价值还是前i-1件物品的总价值,即dp[i][j] = dp[i - 1][j]。

最终放还是不放呢?取二者的最大值:dp[i][j] = max{dp[i - 1][j - w[i]] + v[i] , dp[i - 1][j]}

2.伪代码描述

总结以上三点,现在开始枚举所有情况,假设物品件数为m,背包重量为n,用伪代码表示:

int dp[m+1][n+1];//为什么+1,因为枚举时有取前0件和背包重量为0的情况
dp[0][?] = dp[?][0] = 0;//两种初始值情况

for(i = 1; i <= m; ++i){
	for(j = 1; j<= n; ++j){
		if(背包容量为j时装不下第i件物品){
			dp[i][j] = dp[i - 1][j];
		}
		else if(背包容量为j时能装下第i件物品){
			//进行决策,选择装还是不装第i件物品
			dp[i][j] = max{dp[i - 1][j - w[i]] + v[i], dp[i - 1][j]};
		}
	}
}

3.备注

此处有一点需要注意,不理解很容易陷入误区:在考虑第i件物品要不要取时,前面已经选择的物品并不是固定不变的,即假设我在容量为4的时候选择了第一、二、三件物品,在容量为5的时候我可能会放弃第二件而装入第四件物品,反正是怎么更好怎么选。

4.使用C++语言描述

将上面的案例参考为代码转换为代码.注意,上面提到过,小写w[i]、v[i]对应的是大写W[i - 1]、V[i - 1]:

int package01(int m, int n, vector<int>& W, vector<int>& V){
	vector<vector<int>> dp(m+1, vector<int>(n+1, 0));//将二维数组所有值初始化为0
	for(int i = 1; i <= m; ++i){//枚举只考虑前1,2,3...i件物品的情况
		for(int j = 1; j <= n; ++j){//枚举背包容量为1,2,3...j的情况
			if(j < W[i-1]){//背包容量为j时装不下第i件物品
				dp[i][j] = dp[i - 1][j];
			}else{//背包容量为j时能装下第i件物品
				//进行决策,选择装还是不装第i件物品
				dp[i][j] = max(dp[i - 1][j], dp[i - 1][j - W[i-1]] + V[i - 1]);
			}
		}
	}
	return dp[m][n];
}

5.画图表示代码执行过程

  1. 首先,建立二维数组的过程可以理解为画了一张(m+1)*(n+1)的表格,即红色区域,dp[i][j]即为每一个红色格子:在这里插入图片描述
  2. 初始值:
    在这里插入图片描述
  3. 代码执行过程:
    在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

算法设计与分析 0-1背包问题 动态规划解法【超详细】 0-1背包问题 问题描述 给定i个物品和一个容量为的背包,物品的重量是Wi,其价值为Vi 物品个数为i,背包容量为C。 如何选择装入背包内的物品,使得装入背包中的物品的总价值最大? 其中,每种物品只有全部装入背包或不装入背包两种选择。 物品不能分割,不能重复使用。 动态规划算法思路 首先建立一个数组B[i][c],最上面一行表示背包容量,最左边一列表示物品编号,中间填充的数值表示当当前背包容量为C... 阅读详情

相关推荐

动态规划之01背包问题(Knapsacks Problem)

背包问题 一、01背包问题

Netown_Ethereal的专栏 5854

动态规划——01背包问题

面向小白的动态规划之01背包问题的详细讲解

Wu_L7的博客 3万+

算法——动态规划之0-1背包问题

打算每天复习一点算法内容,就先从动态规划下手。曾经动态规划让我头疼,重新学了一下觉得还好啦不是很难,实现动态规划算法的核心在于实现它的递推公式,写出递推公式,代码也就很容易了。动态规划类似分治法,都是将一个大问题分解为一个个小问题,分而治之。不同之处在于,动态规划记忆了重复的子问题,避免了运算过程中的重复计算。适用情况:有重叠子问题和最优子结构性质(动态规划每一步求的都是最优解)的问题。下面我们通...

Astar的博客 1万+

动态规划背包问题之01背包详解

动态规划背包问题之01背包详解

晨的博客 5万+

经典动态规划:0-1 背包问题

前言 经过前面三篇动态规划文章的介绍,相信大家对动态规划、分治、贪心有了充分的理解,对动态规划的 3 个核心问题、其本质也有了了解。 纸上得来终觉浅,绝知此事要躬行。 那么今天开始我们来聊聊具体的那些面试时常考的题目。 (还没有看过前三篇文章的同学齐姐叫你补课啦~) (一):初识动态规划 (二):动态规划的 3 个核心问题 (三):动态规划的本质 问题背景 月黑风高的夜晚,张三开启了法外狂徒模式:他背着一个可装载重量为 W 的背包去地主家偷东西。 地主家有 N 个物品,每个物品有重量和价值两个属性,其中第

码农田小齐 1659

动态规划 之 0-1背包问题

关于背包问题,其实可以分为两种类型:0-1背包问题 和 部分背包问题。 1、先通过一个例子来说明一下二者的区别吧! 有一个窃贼在偷窃一家商店时发现有n件物品,第i件物品价值为vi元,重量为wi,假设vi和wi都为整数。他希望带走的东西越值钱越好,但他的背包中之多只能装下W磅的东西,W为一整数。他应该带走哪几样东西? 0-1背包问题:每件物品或被带走,或被留下,(需要做出0-1选择)。小偷

小邓笔记 3万+

九种 0-1 背包问题详解

目录 动态规划概念 问题1:0-1背包问题 问题2:完全背包问题 问题3:多重背包问题 问题4:混合背包问题 问题5:二维背包问题 问题6:分组背包问题 问题7:有依赖的背包问题(困难) 问题8:背包问题求方案数 问题9:背包问题求具体方案 前言 0-1 背包是一个经典的问题,之前也整理过一篇关于 0-1 背包的博客,当时只是整理了 0-1 背包问题的4 种解决方法。最近在复习算法,发现有很多 0-1 背包问题的衍生问题。0-1 背包问题的限制条件既可以是重量,也可以是容量,或者..

Tyler_Zx的博客 2万+

动态规划法如何来解决0-1背包问题

1、0-1背包问题。设有n个物品他们的重量和价值分别存放在数组w[]和v[]中,背包的容量存放在全局变量C中,和最终的n个物品是否装入情况存放在数组x[n]中。 2、int KnapSack(int w[],int v[],int x[],int n)函数功能是返回能装载的最大价值。并且第i个物品能否装入背包存放在数组元素x[i]中,它为1(非0)表示该物品可以装入,为0表示该物品不装入。 3、写主函数main(),实现输入数组w[]和v[],调用KnapSack函数,并输出装入物品的编号。 (1)解题思路

JobinXin的博客 3332

彻底搞懂0-1背包问题(动态规划)

看了很多网上的博客,发现对于0-1背包问题很多讲的都很专业,初学者学起来还是比较吃力,今天我就用最简单最形象的语言来描述一下0-1背包问题,为什么不能用贪婪算法,而要选择使用动态规划。 首先对于0-1背包问题,我们需要知道的是:每一个物品只有1个,要么全拿,要么不拿,最后使得拿到的物品的总价值最大。 假如一个小偷有一个可以容纳4千克的背包,但是发现面前只有有3样物品可以偷:台灯(30元,4千克)、音响(20元,3千克)、充电宝(15元,1千克)(价格和重量可能有点奇怪????)。问,小偷能够偷到的物品的

HarryXu的博客 2万+

动态规划--经典01背包问题

尝试用dp[i][j]来表示一个子问题,即选择[0 -- i-1]中能否通过选择几个元素使得他们的和为j,这样dp[len][target]就会是所有元素中选择几个元素是否能使得他们的和变为target(数组和的一半)考虑当前元素是否选择,若选择,则代表dp[i-1][j - num[i]]会是true(即前面的选择中能够使和为j-num[i] 再选上当前元素即可 和变为j)V = 4时,由于B重量为4 不可以选取,由于此时A也可以选,B也可以选,则比较两者价值,发现B更大,则选B。

manfulshark的博客 857

全志 T527_Android13 编译 [ 避坑必看 ]

Swap 概念: Linux中Swap(即:交换分区),类似于Windows的虚拟内存,就是当内存不足的时候,把一部分硬盘空间虚拟成内存使用,从而解决内存容量不足的情况。它的功能就是在内存不够的情况下,操作系统先把内存中暂时不用的数据,存到硬盘的交换空间,腾出内存来让别的程序运行。当输入编译命令make -j16 的时候,会有如下提示,这是官方建议通过减少编译线程来解决编译时消耗内存过大的问题。Android 13 系统的编译流程,编译一共分为两部分:内核编译与 Android 编译。

公众号:嵌入式分享 2111

动态规划解决0-1背包问题详解(图文并茂)

动态规划解决0-1背包问题 这个是网上比较好的案例,因为原文有些地方晦涩难懂,对于刚接触动态规划问题的朋友来说很不友好,所以很对地方加入了我自己的见解,也是作为我的一次学习历程。 一、问题描述: 有n 个物品,它们有各自的重量和价值,现有给定容量的背包,如何让背包里装入的物品具有最大的价值总和? 二、总体思路: 根据动态规划解题步骤(问题抽象化、建立模型、寻找约束条件、判断是否满足最优性原理、找大...

BigData_Mining的博客 1万+

【ESP32】ESP32连接JY61P并通过WIFI发送给电脑

ESP32S连接JY61P并通过WIFI把姿态数据发送给电脑1.采用Arduino IDE编译器;需要安装ESP32的开发板管理器;2.电脑接受数据是基于python的;

Doudou_Nai的博客 1131

动态规划之0/1背包问题原理详解: 简明、细致、深入理解

动态规划,0/1背包问题,回溯

yw906002599的博客 1万+

利用ENVI处理TIF文件,把多个tif整合到一个完整的tif,例如2003-2011年的tif整合到一个tif上。

利用ENVI处理TIF文件,把多个tif整合到一个完整的tif,例如2003-2011年的tif整合到一个tif上。

unique_sir的博客 1万+

将点云坐标转换成世界坐标的demo

将点云坐标转换成世界坐标的demo

howard789的博客 2206

动态规划-(0-1)背包问题

下面我用容积代表重量(我是不会承认我看走眼了的。又懒得改。)0-1背包问题是动态规划背包问题系列的最基础的一个问题。相对理解起来较为简单。按书上来说,要证明一个问题是否可以使用动态规划思想,需要满足最优子结构的性质,那么什么是最优子结构的性质呢?书上给出的定义如下图看起来很拗口,其实就是不论过去状态和决策如何,对前面的决策所形成的状态而言,余下的诸决策必须构成最优策略。说白了就是一个最优策略的子策略也是必须是最优的,而所有子问题的局部最优解将导致整个问题的全局最优。

菜鸟的博客 1万+

华为云HCS解决方案笔记HUAWEI CLOUD Stack【面试篇】

华为云解决方案介绍、华为云服务介绍,华为云网络平面规划等

weixin_48375618的博客 1万+

动态规划解0-1背包问题

动态规划解0-1背包问题 动态规划解0-1背包问题是一个十分典型案例,我从网上查询好多相关资料,但是大部分都深奥难懂,并不适合初学算法的小白,其中涉及的递推关系式、填表,以及最后的二维表简化为一维表的优化过程,好多都是一笔带过,所以,今天就尽我所能,来叙述一下对于0-1背包问题使用动态规划来求解。 要解决0-1背包问题,首先咱们要解决的是什么是动态规划。 动态规划 先说一说什么是动态规划。 动态规划算法与分治算法类似,其基本思想也是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到原问题

weixin_49571787的博客 6432

深入理解EtherCAT状态机:从IGH代码看伺服电机如何从‘上电’到‘使能’

本文深入解析EtherCAT状态机的工作原理,重点探讨伺服电机从'上电'到'使能'的状态转换过程。通过分析状态字(Status Word)和控制字(Control Word)的交互机制,结合IGH代码实例,揭示DS402状态机的核心逻辑,帮助工程师解决60%以上的伺服控制问题,提升EtherCAT网络调试效率。

weixin_42549037的博客 288

团队管理中最棘手的6个问题

研发团队的管理棘手问题,大多集中在。

xiaolyuh的专栏 742

动态规划法解决0/1背包问题详解

强烈推荐一个大神的人工智能的教程:http://www.captainbed.net/zhanghan 是什么 动态规划(dynamic programming)是求解决策过程最优化的数学方法,把多阶段过程转换为一系列单阶段问题,利用各阶段之间的关系,逐个求解,创立了解决这类过程优化问题的新方法。 基本思想 将待求解的问题分解成若干个子问题,先求解子问...

至尊宝 3万+

【异常】API 速率限制报错问题全流程排查与解决指南 API rate limit reached. Please try again later.

摘要: 本文针对大模型API开发中常见的速率限制报错("API rate limit reached")提供全流程解决方案。首先解析该报错的本质是服务端对高频调用的保护机制,通过三步排查法确认根因:客户端请求频率超出账户阈值。提出三级解决方案:1)临时等待限流周期重置;2)升级付费账户提高调用配额;3)构建多模型容灾架构实现自动切换。建议生产环境优先采用容灾方案,通过备用API节点保障业务连续性,同时平衡不同模型服务的成本与性能。

奶爸的编程之路,也就一周冷个三天 1423

动态规划0-1背包问题。(算法设计与分析详解)

背包问题通俗的说,就是假如你面前有5块金块速分别为a, b, c, d, e,每块金块的重量不同,并且每块金块所带来的价值也不同(注意:这里金块的重量的价值没有特定关系),目前我们有一个背包,只有固定的容量,要解决的问题就是在一定容量的背包面前装哪几块金块才能获取到最大的价值,对于每块金块我们只有拿或者不拿这两种选择,拿为1不拿为0,因此叫做0-1背包问题。下面我们给出思想,以及步骤。

q805370101的博客 5791

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

动态规划-经典问题(0-1背包问题)分析及优化

目录 1.0-1背包问题的分析 (1)状态方程 2.递归算法 3.记忆化搜索 4.动态规划 5.优化1——空间复杂度O(2C) 6.优化2——空间复杂度O(C) 7.0-1背包问题的变种 如上图是一个LeetCode的经典问题,0-1背包问题 1.0-1背包问题的分析 尝试下面的算法 暴力解法:每一件物品都可以放进背包,也可以不放进背包,时间复杂度为O((2^n)...

YY-帆S的博客 1万+

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

0-1背包问题(动态规划)

动态规划的核心思想就是把一个大问题分解成很多小问题,然后逐个解决这些小问题,最后把这些小问题的解组合起来,就得到了大问题的解。为什么要用动态规划?有些问题直接解决很难,但是分解成小问题就容易多了。很多小问题是重复的,我们可以把这些小问题的解保存起来,避免重复计算。背包问题,就像在玩一个非常有趣的“装箱”游戏!想象一下,你有一个背包,它只能装下一定重量的东西。现在,你面前有一堆玩具,每个玩具都有自己的重量和价值,每个玩具只能装一个。在背包的重量限制下,装下尽可能多的玩具,并且让这些玩具的总价值最高。

m0_74062928的博客 2700

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

上一篇: 236. 二叉树的最近公共祖先
下一篇: 509. 斐波那契数
MegaBytes
博客等级 码龄8年 45粉丝 115原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值