1269:【例9.13】庆功会
时间限制: 1000 ms 内存限制: 65536 KB
提交数: 8343 通过数: 4803
【题目描述】
为了庆贺班级在校运动会上取得全校第一名成绩,班主任决定开一场庆功会,为此拨款购买奖品犒劳运动员。期望拨款金额能购买最大价值的奖品,可以补充他们的精力和体力。
【输入】
第一行二个数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
思路:二进制优化,1~ m可以用这些数的组合构成: 1 2 4 8…2^x (+ 剩余的数)。1到n以内的数字,能够通过 n 内的进制数组合得到,比如 9以内的二进制数有 1 2 4 8,可以自己试一下, 3 = 1 + 2 ,5=1 + 4 ,6= 2 + 4,所以,我们可以利用二进制数的拆分求出所有 n 以内的数;拆分的过程:9 - 1 = 8; 8 - 2 = 6; 6 - 4 = 2 ; 2 - 8 < 0; 那么要求的 9 以内的二进制数就是 1,2, 4,2,这几个二进制是能够组成 9以内包括 9 的所有整数,然后通过 w[ i ] 乘以这些二进制数,把他们当作一件物品来做01背包的处理,当然,如果没有用二进制拆分的话就用朴素方法来做。二进制优化,简单来说,就是把一个数字分成 (1 2 4 8…最大数) 这样下去的类型为什么呢? 因为这些数字可以组成(1~最大数)中的任何一个数我们可以实现组合把这些抽出来变成一个新的产品,不过 重量和价值 有所不同。变成:
一件 v[i]*1 , w[i]*1
一件 v[i]*2 , w[i]*2
一件 v[i]*4 , w[i]*4
一件 v[i]*8 , w[i]*8
#include <iostream>
#include <cstdio>
using namespace std;
#define N 10000
int c[N], w[N], num[N];
int f[N], new_c[N], new_w[N];
int v, m, tot;
int main()