背包九讲(还没写完
背包九讲的个人整理
1.01背包
题目
N种物品,每种物品只有一个,背包容量为V,第i件物品的所占空间为v[i],价值是w[i]。
在不超过背包容量的前提下,求最大化价值之和
基本思路
对于一个物品我们可以选择放或者是不放
用子问题来定义状态:f[i][j]选到第i个物品时,容量为j的背包的最大化价值之和(需要注意的是此时背包不一定需要装满)则其状态转移方程为
f[i][j]=max(f[i-1][j],f[i-1][j-v[i]]+w[i]);
这个方程非常重要,几乎所有背包问题都与它相关或由其衍生
因为我们只对第i件物品进行考虑(即有两种方案:放或者是不放)
选择不放时:f[i][j]=f[i-1][j];
选择放时 :f[i][j]=f[i-1][j-v[i]]+w[i];
优化空间
以上方法的时间和空间复杂度都是Θ(V*N),时间复杂度已经不能继续优化了,但空间复杂度却能优化到Θ(V);
先考虑上述的基本思路如何实现肯定是有一个主循环for i 1~N
每次算出f[i][0~V]
的 值
那么能否只用一个数组f[0~V]
保证每次循环完成得到的f[j]
就是我们想要的f[i][j]
呢?
即优化代码之后:
for(int i=1;i<=N;i++)
for(int j=V;j>=v[i];j--)
f[j]=max(f[j],f[j-v[i]]+w[i]);//等价于f[i][j]=max(f[i−1][j],f[i−1][j−c[i]]+w[i])
例题练习
luogu P1048 [NOIP2005 普及组] 采药
luogu P1049 [NOIP2001 普及组] 装箱问题
luogu P1060 [NOIP2006 普及组] 开心的金明