ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

背包问题(一) 01背包

2022-07-29 19:36:49  阅读:147  来源: 互联网

标签:背包 容量 max 复杂度 问题 枚举 01 物品


题目释义

有一个背包容量为 \(m\) 的背包,\(n\) 个物品。每个物品的重量为 \(w\),价值为 \(v\) 。

要求在选取物品总重量不大于背包容量的情况下,使得选取物品总价值最大。

每种物品仅可使用一次。

分析

首先,我们用 \(f[i][j]\) 表示前 \(i\) 个物品放入容量为 \(j\) 的背包的最大价值。

对于每个物品,我们只有两个选择,即放和不放。

  • 若放入背包,则 \(f[i][j] = f[i-1][j-w[i] ]+v[i]\)。

  • 若不放入背包,则 \(f[i][j]=f[i-1][j]\)。

  • 但我们还要考虑,背包容量不足时也不能放入背包。

因此,状态转移方程为

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

Code:

for(int i = 1;i <= n;i++)// 依次枚举每个物品; 
	for(int j = m;j >= 0;j--)// 枚举背包容量; 
		if( j >= w[i] )// 放得下; 
			f[i][j] = max(f[i-1][j],f[i-1][ j-w[i] ]+v[i]);
		else// 放不下; 
			f[i][j] = f[i-1][j];

以上的代码时间复杂度空间复杂度均为 \(O(nm)\),若题目中给出 \(n,m \leq\) \(10000\) ,它可能就会出现 MLE 的情况。

优化

我们发现,\(f[i][j]\) 只与 \(f[i-1][...]\) 有关,那我们可以优化掉数组的第一维,直接用 \(f[j]\)
来表示处理到当前物品时背包容量为 \(j\) 时的最大价值,
得出以下方程:

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

注意: 为防止之前的值被覆盖,需要逆向枚举背包容量。

而原先未经优化的代码无需考虑背包容量的枚举顺序。

空间复杂度由 \(O(nm)\) 降至 \(O(m)\)。

Code

for(int i=1;i<=n;i++)
	for(int j=m;j>=w[i];j--)// 逆向枚举;
		f[j]=max(f[j],f[ j-w[i] ]+v[i]);

例题

P2871 [USACO07DEC]Charm Bracelet S(模板)

P1048 [NOIP2005 普及组] 采药(模板)

P1049 [NOIP2001 普及组] 装箱问题

P1060 [NOIP2006 普及组] 开心的金明

标签:背包,容量,max,复杂度,问题,枚举,01,物品
来源: https://www.cnblogs.com/JXYBJ/p/01beibao.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有