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
借用二进制。
首