DP背包问题

最近在ICPC备赛,背包DP对于我来说一直都是难点,今天看到几个博文写的挺好的,在此转载一下


01背包

(每个物体只能拿一次,要求在一定的空间内,拿物体使得到的价值最大)

有两种写法,一种是二维数组,一种是一维数组(省空间)
1.二维dp的模板

状态转移方程:dp[i][j]=max(dp[i-1][j],dp[i-1][j-wei[i]]+val[i]);
 
基本操作:
 
if(j>=wei[i])
{
	dp[i][j]=max(dp[i-1][j],dp[i-1][j-wei[i]]+val[i]);//i为面对第几个物体了
    //j为所占的空间大小下,dp数组存的是对应的价值
}
else//这种写二维的方式可不清空 
{
	dp[i][j]=dp[i-1][j];
}


2.一维dp模版

状态转移方程:dp[j]=max(dp[j],dp[j-wei[i]]+val[i]);
 
基本操作:
 
memset(dp,0,sizeof(dp));//一维记得清空 
for(int i=1;i<=n;++i)
{
	for(int j=v;j>=wei[i];--j)
	{
		dp[j]=max(dp[j],dp[j-wei[i]]+val[i]);
	}
}
cout<<dp[v]<<endl;


总结:简单来说就是对于每一个物体有两种选择,要么拿要么不拿,如不拿就继承上一个状态,否则就上一个状态的dp的值加上当前物体的价值。


二:完全背包问题

(每个物体可以拿无数次,要求在一定的空间内,拿物体使得到的价值最大)

板子:

状态转移方程:dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

基本操作:

for(i=1;i<=n;i++)
      for(j=w[i];j<=m;j++)  //注意此处与01背包不同,01为倒序
 
             dp[j]=max(dp[j],dp[j-w[i]]+v[i]);

优化:若两件物品i、j满足c[i]<=c[j]且w[i]>=w[j],则将物品j去掉,不用考虑。

三、多重背包问题

(每个物体最多可以拿c【i】次,即次数限制可能不同。要求在一定的空间内,拿物体使得到的价值最大)

板子:(该板子参考:https://blog.csdn.net/qq_41117236/article/details/80986564)

状态转移方程:dp[j]=MAX{dp[j],dp[j-kw[i]]+kv[i]};

基本操作:

 
for(i=1;i<=n;i++)
      for(j=m;j>=0;j--)
           for(k=0;k<=c[i];k++) 
           {
                if(j-k*w[i]<0)   break;
                dp[j]=max(dp[j],dp[j-k*w[i]]+k*v[i]);
          }

转载声明:本文为CSDN博主「suheyin」的原创文章
原文链接:https://blog.csdn.net/suheyin/article/details/86485399

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值