01背包基本问题

这篇博客介绍了如何使用动态规划解决01背包问题,通过一个具体的例子展示了算法的运行过程,并提供了相应的代码实现。内容包括问题描述、输入输出格式、贪心算法的不足以及动态规划的解决方案。动态规划的核心在于创建一个二维数组,通过递推公式填充,找到前n个物品在背包容量不超过m时的最大价值。文章强调了手动模拟过程对于理解算法的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

假设我们面临一个问题

题目

题目描述

有一个容量为 m 的背包 , 有 n 件物品可以挑选 , 每个物品有 2 个属性 :体积及价值 。

求背包能装下的最大价值是多少?

输入格式

第1行 2 个正整数 , n, m 代表物品个数与背包容量。

接下来 n 行每行 2 个正整数 ,  w[i]表示第 i 个物品的体积 , v[i]表示第 i 个物品的价值

输出格式

输出1个整数 , 即能装下的最大价值。

输入样例

4 6
1 4
2 6
3 12
2 7 

输出样例

23

数据范围

1 <= n,m <= 1000;1 <= w[i],v[i] <= 400

分析

假设有三个物品:吉他(价值15 重量1),笔记本(价值20 重量3),音响(价值30 重量4)

 并且背包容量是4

贪心算法

按照贪心的想法,要获得最大价值应该先拿价值最大的物品,也就是音响,价值30,但是如果这样一拿,背包就直接装满了,也就是说最终得到价值30的东西,但我们可以很快构造出价值35的组合:吉他+笔记本。所以,贪心算法是难以解决此问题的。

那有没有一种算法能快速解决此问题呢?

动态规划算法

我们可以创建一个数组F

//f[i][j]表示前i个物品,背包容量不超过j时的最大价值

用图像说明的话就是:

 那接下来的任务就是如何填充此表格了

首先看第一行,我们知道吉他的重量是1,价值是15,所以选取吉他并且重量不超过1的最大价值就是吉他的价值15。接下来一想,显然,这一行都是15

 再来看第二行,我们知道笔记本的重量是3,价值是20,那么看这一行的第一格,它的意义是前2个物品中,背包容量不超过1的最大价值。因为容量限制在1以内,所以只能是一个吉他,价值15

 第二格,表示前2个物品中,背包容量不超过2的最大价值。这时候我们有两个选择:

  1. 不选择笔记本,最大价值就是前1个物品中背包容量不超过2的最大价值,就是15
  2. 选择笔记本,最大价值就是前1个物品中(因为已经选了笔记本)背包容量不超过2-笔记本重量的最大价值

但是笔记本的重量是大于2的,所以只能选择方案1,价值还是15

接下来看第三格,同样,两个选择:

  1.  不选择笔记本,最大价值就是前1个物品中背包容量不超过3的最大价值,就是15
  2. 选择笔记本,最大价值就是前1个物品中(因为已经选了笔记本)背包容量不超过3-笔记本重量的最大价值

这是方案2就可行,因为笔记本重量=3,所以方案2所得的价值是20+前0个……,也就是20嘛

欸,那这时,20 > 15,所以这时方案2会优于方案1,选择方案2

因此,我们可以得到递推式

f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + v[i]);

其中,f[i - 1][j]为不选第i件物品的最大价值,f[i - 1][j - w[i]] + v[i]为选第i件物品的最大价值

我们就是在这两个值中取较大的

所以表格剩下的也就按照这个递推式来进行即可

最终答案是表格的右下角也就是 f[n][m],最大价值35

但在递推式中,需要注意的是,如果j < w[i]时,就只能是 f[i - 1][j]

我们还需要考虑初始值,其实这很容易,如果这一上来体积就大于背包容量了,那所拿的价值就是0,所以 f 数组中每一项初始值为0

此时,算法原理已经讲完了,而代码实现难度并不高,我们直接来看代码

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int w[1010],v[1010];
//w[i]表示第i件物品的重量,v[i]表示第i件物品的价值
int f[1010][1010];
//f[i][j]表示前i个物品重量不超过j的最大价值

int main() 
{
	int n,m;
	cin >> n >> m;
	for(int i = 1;i <= n;i++)
	{
		cin >> w[i] >> v[i];
	}
	for(int i = 1;i <= n;i++)
	{
		for(int j = 1;j <= m;j++)
		{
			f[i][j] = f[i - 1][j];
			if(j - w[i] >= 0)
				f[i][j] = max(f[i - 1][j],f[i - 1][j - w[i]] + v[i]);
		}
	}
	cout << f[n][m];
    return 0;
}

最后,如果你没有理解这个算法的话,我强烈建议你手动模拟一下整个过程,这样,你的理解程度会更深一些。

有兴趣的话可以看一下下一篇01背包一维优化

内容概要:《2024年中国城市低空经济发展指数报告》由36氪研究院发布,指出低空经济作为新质生产力的代表,已成为中国经济新的增长点。报告从发展环境、资金投入、创新能力、基础支撑和发展成效五个维度构建了综合指数评价体系,评估了全国重点城市的低空经济发展状况。北京和深圳在总指数中名列前茅,分别以91.26和84.53的得分领先,展现出强大的资金投入、创新能力和基础支撑。低空经济主要涉及无人机、eVTOL(电动垂直起降飞行器)和直升机等产品,广泛应用于农业、物流、交通、应急救援等领域。政策支持、市场需求和技术进步共同推动了低空经济的快速发展,预计到2026年市场规模将突破万亿元。 适用人群:对低空经济发展感兴趣的政策制定者、投资者、企业和研究人员。 使用场景及目标:①了解低空经济的定义、分类和发展驱动力;②掌握低空经济的主要应用场景和市场规模预测;③评估各城市在低空经济发展中的表现和潜力;④为政策制定、投资决策和企业发展提供参考依据。 其他说明:报告强调了政策监管、产业生态建设和区域融合错位的重要性,提出了加强法律法规建设、人才储备和基础设施建设等建议。低空经济正加速向网络化、智能化、规模化和集聚化方向发展,各地应找准自身比较优势,实现差异化发展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值