多重背包问题(两种思路) 以 一本通 1269庆功会 为例

博客详细探讨了多重背包问题,与完全背包的区别,并提供了两种解决思路。第一种思路是通过调整完全背包的三重循环,考虑物品数量限制。第二种思路利用二进制分解,降低了算法复杂度。并附带了两种思路的代码实现。
摘要由CSDN通过智能技术生成

1269:【例9.13】庆功会

【题目描述】
为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。

【输入】
第一行二个数n(n≤500),m(m≤6000),其中n代表希望购买的奖品的种数,m表示拨款金额。
接下来n行,每行3个数,v、w、s,分别表示第I种奖品的价格、价值(价格与价值是不同的概念)和能购买的最大数量(买0件到s件均可),其中v≤100,w≤1000,s≤10。
【输出】
一行:一个数,表示此次购买能获得的最大的价值(注意!不是价格)。
【输入样例】
5 1000
80 20 4
40 50 9
30 50 7
40 30 6
20 20 1

【输出样例】
1040

**

分析:

**
多重背包与完全背包的区别在于完全背包是每种物品都是无限的。而多重背包是每种物品的个数是有规定的。分析中仍用w[i]表示代价,v[i]表示价值。m表示总钱数,即能负担的起的总代价。

思路一:(理解起来比较简单)
接着完全背包三重for循环的思路来理解,在完全背包中k的确定只有一个限制条件,那就是 j/w[i] (代价),是容量j来限制的。但是多重背包中的k的限制条件不仅有容量j,还有问题中给出的存在数量s[i]。所以 k = min(s[i], j/w[i])。应该取一个最小值。其他的就与完全背包的for三重循环的思路代码一样。ps:完全背包问题的三个for循环思路可参考另一篇博客:https://blog.csdn.net/qq_40575034/article/details/103510045

按照这个思路的核心代码为:

for(int i=1;i<=n;i++)
 {
   
  for(int j=m;j>=w[i];j--)//从后往前 
  {
   
   max_z=0;
   num=min(s[i],j/w[i]);// 选取能够买的到的最大的数量 
   for(int k=0;k<=num;k++)
   {
   
    if(max_z<a[j-k*w[i]]+k*v[i])//将k=0~max_k数量依次遍历 ,找最大值
     max_z=a[j-k*w[i]]+k*v[i];
    } 
   a[j]=max_z;
  }

思路二:(理解起来有些困难,但是算法比较高级,有一些省略,算法复杂度降低)
参考大神博客。https://blog.csdn.net/hebtu666/article/details/100585136
借用二进制

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值