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]]已经被更新过了,就不再是上一个状态

扫描二维码关注公众号,回复: 2467529 查看本文章

所以我们逆序求,保证下标小的未被更新即可

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  多重背包

猜你喜欢

转载自www.cnblogs.com/raincle/p/9392542.html