C++背包问题——01背包
01背包问题
- 1、题目
- 2、基本思路
- 3、优化空间复杂度
- 4、初始化的细节问题
- 5、小结
- 6、代码
1、题目
有N件物品和一个容量为 V V V的背包。放入第i件物品耗费的空间是 C i Ci Ci,得到的价值是 W i Wi Wi。
求解将哪些物品装入背包可使价值总和最大。
2、基本思路
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
用子问题定义状态:即 F [ i , v ] F[i, v] F[i,v]表示前i件物品恰放入一个容量为 v v v的背包可以获得的最大价值。
则其状态转移方程便是:
F[i, v] = max{F[i - 1, v], F[i-1, v-Ci] + Wi}
这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:
将前 i i i 件物品放入容量为 v v v 的背包中”这个子问题,若只考虑第 i i i 件物品的策略(放或不放),那么就可以转化为一个只和前 i − 1 i-1 i−1 件物品相关的问题。
如果不放第 i i i件物品,那么问题就转化“前 i − 1 i-1 i−1件物品放入容量为 v v v的背包中,价值为 F [ i − 1 , v ] F[i-1, v] F[i−1,v];
如果放第i件物品,那么问题就转化为“前i件物品放入剩下的容量为 v − C i v-Ci v−Ci的背包中,此时能获得的最大价值就是 F [ i − 1 , v − C i ] F[i -1, v -Ci] F[i−1,v−Ci]再加上通过放入第 i i i 件物品获得的价值 W i Wi Wi。
伪代码如下:
F[0, 0→V ] = 0
for i = 1 to Nfor v = Ci to VF[i, v] = max{F[i i 1, v], F[i i 1, v v Ci] + Wi}
3、优化空间复杂度
以上方法的时间和空间复杂度均为 O ( V N ) O(V N) O(VN),其中时间复杂度应该已经不能再优化了,但空间复杂度却可以优化到 O ( V ) O(V ) O(V)。
先考虑上面讲的基本思路如何实现,肯定是有一个主循环 i = 1 → N i = 1→N i=1→N,每次算出来二维数组 F [ i , 0 → V ] F[i, 0→V ] F[i,0→V]的所有值。那么,如果只用一个数组 F [ 0 → V ] F[0→V ] F[0→V],能不能保证第i次循环结束后 F [ v ] F[v] F[v]中表示的就是我们定义的状态 F [ i , v ] F[i, v] F[i,v]呢?
F [ i , v ] F[i, v] F[i,v]是由 F [ i − 1 , v ] F[i -1, v] F[i−1,v]和 F [ i − 1 , v − C i ] F[i -1, v -Ci] F[i−1,v−Ci]两个子问题递推而来,能否保证在推 F [ i , v ] F[i, v] F[i,v]时(也即在第 i i i次主循环中推 F [ v F[v F[v]时)能够取用 F [ i − 1 , v ] F[i -1, v] F[i−1,v]和 F [ i − 1 , v − C i ] F[i -1, v - Ci] F[i−1,v−Ci]的值呢?
事实上,这要求在每次主循环中我们以 v = V → 0 v = V→0 v=V→0的递减顺序计算 F [ v ] F[v] F[v],这样才能保证推 F [ v ] F[v] F[v]时 F [ v − C i ] F[v - Ci] F[v−Ci]保存的是状态 F [ i − 1 , v − C i ] F[i -1, v - Ci] F[i−1,v−Ci]的值。
伪代码如下:
F[0 → V ] = 0
for i = 1 to Nfor v = V to CiF[v] = max{F[v], F[v - Ci] + Wi}
其中的 F [ v ] = m a x F [ v ] , F [ v − C i ] + W i F[v] = max{F[v], F[v -Ci] + Wi} F[v]=maxF[v],F[v−Ci]+Wi 一句,恰就对应于我们原来的转移方程,因为现在的 F [ v − C i ] F[v - Ci] F[v−Ci]就相当于原来的 F [ i − 1 , v − C i ] F[i -1, v- Ci] F[i−1,v−Ci]。
如果将v的循环顺序从上面的逆序改成顺序的话,那么则成了 F [ i , v ] F[i, v] F[i,v]由 F [ i , v − C i ] F[i, v -Ci] F[i,v−Ci]推导得到,与本题意不符。
事实上,使用一维数组解01背包的程序在后面会被多次用到,所以这里抽象出一个处理一件01背包中的物品过程,以后的代码中直接调用不加说明。
def ZeroOnePack(F, C, W)for v = V to CF[v] = max(F[v], f[v v C] + W)
有了这个过程以后,01背包问题的伪代码就可以这样写:
for i = 1 to N
ZeroOnePack(F, Ci, Wi)
4、初始化的细节问题
我们看到的求最优解的背包问题题目中,事实上有两种不太相同的问法。
有的题目要求“恰好装满背包”时的最优解,有的题目则并没有要求必须把背包装满。一种区别这两种问法的实现方法是在初始化的时候有所不同。
如果是第一种问法,要求恰好装满背包,那么在初始化时除了 F [ 0 ] F[0] F[0]为 0 0 0,其它 F [ 1 → V ] F[1→V ] F[1→V]均设为 − ∞ -∞ −∞,这样就可以保证最终得到的 F [ V ] F[V ] F[V]是一种恰好装满背包的最优解。
如果并没有要求必须把背包装满,而是只希望价格尽量大,初始化时应该将 F [ 0 → V ] F[0→V ] F[0→V]全部设为 0 0 0。
这是为什么呢?可以这样理解:初始化的 F F F数组 事实上就是在没有任何物品可以放入背包时的合法状态。如果要求背包恰好装满,那么此时只有容量为 0 0 0 的背包可以在什么也不装且价值为 0 0 0 的情况下被“恰好装满”,其它容量的背包均没有合法的解,属于未定义的状态,应该被赋值为 − ∞ -∞ −∞了。
如果背包并非必须被装满,那么任何容量的背包都有一个合法解“什么都不装”,这个解的价值为 0 0 0,所以初始时状态的值也就全部为 0 0 0了。
这个小技巧完全可以推广到其它类型的背包问题,后面也就不再对进行状态转移之前的初始化进行讲解。
5、小结
01 01 01背包问题是最基本的背包问题,它包含了背包问题中设计状态、方程的最基本思想。另外,别的类型的背包问题往往也可以转换成 01 01 01背包问题求解。
故一定要仔细体会上面基本思路的得出方法,状态转移方程的意义,以及空间复杂度怎样被优化。
6、代码
#include <bits/stdc++.h>
using namespace std;
int v,n,d[2000],c[50],w[50]; //d数组的下标表示容量
int main()
{cin >>v >>n; //v表示容量,n表示数量 for (int i=1;i<=n;i++)cin >>w[i] >>c[i];for (int i=1;i<=n;i++) for (int j=v;j>=w[i];j--){d[j]=max(d[j],d[j-w[i]]+c[i]); //公式 }cout <<d[v]; //注意不是d[n] return 0;
}
C++背包问题——01背包相关推荐
- 背包问题——01背包
背包问题--01背包 01背包作为动态规划(dynamic programing)中最基础的问题,需要我们彻底理解其中的原理,为以后解决更难的动态规划问题打下良好的基础. 这里拟定一个01背包问题: ...
- 动态规划之背包问题——01背包
算法相关数据结构总结: 序号 数据结构 文章 1 动态规划 动态规划之背包问题--01背包 动态规划之背包问题--完全背包 动态规划之打家劫舍系列问题 动态规划之股票买卖系列问题 动态规划之子序列问题 ...
- C++ 背包问题——01背包
由于编辑器原因,01背包文章搬家了,想看到更好的01背包问题题解,请点击链接: C++背包问题--01背包_小天狼星_布莱克的博客-CSDN博客
- 经典背包问题 01背包+完全背包+多重背包
01 背包 有n 种不同的物品,每个物品有两个属性,size 体积,value 价值,现在给一个容量为 w 的背包,问最多可带走多少价值的物品. int f[w+1]; //f[x] 表示背包容量为x ...
- 背包问题——01背包/完全背包/多重背包
背包问题是典型的动态规划问题,本文将对典型的背包问题进行总结. 0-1背包问题 有 N 件物品和一个容量是 V 的背包.每件物品只能使用一次. 第 i 件物品的体积是 vi,价值是 wi. 求解将哪些 ...
- 动态规划之背包问题---01背包---完全背包---多重背包
本篇博客是基于Carl大佬的刷题笔记 (代码随想录) 进行总结的 另外加入了我自己的一些整理,特此记录,以防遗忘 几种在面试中常见的背包,其关系如下: 通过这个图,可以很清晰分清这几种常见背包之间的关 ...
- 动态规划之背包问题 01背包
什么是01背包? 有n件物品和一个最多能背重量为w 的背包.第i件物品的重量是weight[i],得到的价值是value[i] .每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大. 首先, ...
- 动态规划背包问题——01背包
2022.7.20 题意概要:有n个物品和一个容量为p的背包,每个物品有重量w和价值v两种属性,要求选若干物品放入背包使背包中物品的总价值最大且背包中物品的总重量不超过背包的容量. 在 ...
- 动态规划——背包问题01背包
有n件物品和一个最多能背重量为w 的背包.第i件物品的重量是weight[i],得到的价值是value[i] .每件物品只能用一次,求解将哪些物品装入背包里物品价值总和最大. 动态规划五部曲: 确定d ...
最新文章
- Android-如何开发一个功能强大的图片选择器
- 一文读懂图像局部特征点检测算法
- SpringMVC拦截器之介绍和搭建环境
- LiveVideoStack线上分享第五季(十二):移动端多种通话场景统一技术方案实践...
- PHP内存管理机制与垃圾回收机制
- 【转】如何将域中的AD数据导入SharePoint
- Design-patterns-JS:用JavaScript实现23种设计模式
- mount的api使用笔记
- 【直通BAT】剑指Offer 经典试题整理(5)
- ACL在QinQ port 中的应用
- 3.Prometheus 监控技术与实践 --- Exporter
- 2.Windows 界面技术发展现状
- php sns 源码,ThinkSNS V2.3源码下载(SNS系统)
- 移动端h5原生分享到朋友圈、微博等
- 不是所有的大作业都叫微信抢票大作业
- VMwares设置共享文件夹
- 手机屏幕保护DIY全教程
- 江苏省发布大数据引领推动融合发展专项行动计划
- Spring源码 - 从缓存中获取单例Bean
- Bootstrap3 带边框的表格样式