动态规划背包问题——01背包

问题描述:
n种物品,每种一个。第i种物品的体积为Vi,重量为Wi。选一些物品装到容量为C的背包,使得背包内物品不超过C的前提下,重量最大。

问题分析:
声明一个f[n][c]的数组。f[i][j]表示把前i件物品都装到容量为j的背包所获得的最大重量。
当 j < v[i] 时,背包容量不足以放下第 i 件物品,f[ i ][ j ] = f[ i-1 ][ j ]
当j>=v[i] 时,背包容量可以放下第 i 件物品。
如果拿,f[ i ][ j ]=f[ i-1 ][ j-v[ i ] ] + w[ i ]。 这里的f[ i-1 ][ j-v[ i ] ]指的就是考虑了i-1件物品,背包容量为j-v[i]时的最大价值,也是相当于为第i件物品腾出了v[i]的空间。
如果不拿,f[ i ][ j ] = f[ i-1 ][ j ]
比较这两种情况那种价值最大。

每种物品只有两种情况,拿或者不拿,可以用一个标记数组来记录。
另起一个 flag[ ] 数组,flag[i]=0表示不拿,flag[i]=1表示拿。
f[n][c]为最优值,如果f[n][c]=f[n-1][c] ,说明有没有第n件物品都一样,则flag[n]=0 ; 否则 flag[n]=1。当flag[n]=0时,由f[n-1][c]继续构造最优解;当flag[n]=1时,则由f[n-1][c-w[i]]继续构造最优解。

模板:

memset(f, 0, sizeof(f));
for (int i=1; i<=n; i++){
	for (int j=0; j<=c; j++){
		if (j>=v[i])
			f[i][j]=max(f[i-1][j], f[i-1][j-v[i]]+w[i]);
		else
			f[i][j]=f[i-1][j];	
	}
}
void traceback()
{
    for(int i=n;i>1;i--)
    {
        if(f[i][c]==f[i-1][c])
            flag[i]=0;
        else
        {
            flag[i]=1;
            c-=v[i];
        }
    }
    flag[1]=(f[1][c]>0)?1:0;			把i等于1的情况放在for里面也可以, 因为[0][j]都是0
}

附滚动数组优化:

for (int i=1; i<=n; i++){
	for (int j=c; j>=0; j--){
		if (j>=v[i])
			f[j]=max(f[j], f[j-v[i]]+w[i]);
	}
}

参考链接:https://blog.csdn.net/xp731574722/article/details/70766804

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H4ppyD0g

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值