7.30 背包问题
Posted raincle
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了7.30 背包问题相关的知识,希望对你有一定的参考价值。
1 01背包
问题描述:
有N件物品和一个容量为V的背包。第i件物品的费用是c[i],价值是w[i]。求解将哪些物品装入背包可使价值总和最大。
基本思路 :
这是最基础的背包问题,特点是:每种物品仅有一件,可以选择放或不放。
顺序写:
for(int i=1;i<=n;i++) { for(j=c[i];j<=v;j++) //容量至少要大于c[i]啊,不然就只能不选i了 { f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i]);//选与不选中找大的那一个 } }
这样写要开二维数组,浪费空间
怎么节省空间呢?
观察上面的状态转移方程,可以发现
f[i][j](放前i个物品,容量为j时的最大价值)=max(f[i-1][j](不放第i个物品的上一个状态的价值),f[i-1][j-c[i]]+w[i](放了第i个物品的上一个状态的价值加上 i 物品的价值))
所以我们只要保证我们找到的都是上一个状态即可。
化简为一维数组->f[j] 显然f[j]=max (f[j],f[j-c[i]]+w[i]) 显然括号里的f[j]为上一个状态,那么我们还要保证f[j-c[i]]为上一个状态,如果顺序求,求到f[j]时,f[j-c[i]]已经被更新过了,就不再是上一个状态
所以我们逆序求,保证下标小的未被更新即可
for(int i=1;i<=n;i++) { for(j=v;j>=c[i];j--) { f[j]=max(f[j],f[j-c[i]]+w[i]); } }
2 完全背包
问题描述:有编号分别为a,b,c,d的四件物品,它们的重量分别是2,3,4,7,它们的价值分别是1,3,5,9,每件物品数量无限个,现在给你个承重为10的背包,如何让背包里装入的物品具有最大的价值总和?
完全背包问题与01背包问题的区别在于每一件物品的数量都有无限个,而01背包每件物品数量只有一个。
之前对于01背包逆序求的解释还有一种,即拿完一个就没得了,f[i][j]=max(f[i-1][j],f[i-1][j-c[i]]+w[i] (拿第i个,上一个状态只能拿前i-1个)
而完全背包拿完了还可以再拿,f[i][j]=max(f[[i-1][j] (不拿第i个),f[i][j-c[i]]+w[i] (拿第i个,上一个状态可能仍旧拿的是第i个)
如此对于完全背包,我们不需要保证得到的都是之前的状态,顺序求即可
for(int i=1;i<=n;i++) { for(j=c[i];j<=v;j++) { f[j]=max(f[j],f[j-c[i]]+w[i]); } }
3 多重背包
以上是关于7.30 背包问题的主要内容,如果未能解决你的问题,请参考以下文章