题目描述
新年伊始,我飞瞅准机会要大赚一笔,于是我飞换了一个体积为V的背包。
现在有N种商品,每种商品有Mi件,可以带来的收益为Pi,体积为Vi。
那么问题来了,在所装物品不超过V的前提下的最大收益是多少?
谁能快速的做帮我飞算出来,我飞就让谁出任UFO,迎娶高富帅,走上人生巅峰233。各位准Final巨巨加油啊。
输入
第一行输入一个
T
,代表有
T(1 <= T <= 15)
组数据。
对于每一组数据:
第一行有两个整数N , V。
接下里的N行,每行三个整数Mi,Vi,Pi。
对于所有数据1 <= N <= 200,1 <= V <= 15000,1 <= Mi , Vi, Pi <= 100000。
输出
对于每组数据输出一个整数,代表我飞的最大收益。
示例输入
1 2 10 1 10 10 2 6 21
示例输出
21
提示
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <set>
#include <queue>
#include <stack>
#include <map>
using namespace std;
long long dp[15010];//dp与V有关,p,w与n有关
long long w[100010],p[100010],k[100010];//w价值,p费用,k数量
int n,V;
void ZeroOnePack(int p,int w)//01背包(该种物品只有1个)
{
for(int i=V; i>=p; i--) {
dp[i] = max(dp[i],dp[i-p]+w);
}
}
void CompletePack(int p,int w)//完全背包(该种物品不限量)
{
for(int i=p; i<=V; i++) {
dp[i] = max(dp[i],dp[i-p]+w);
}
}
void MultiplePack(int p,int w,int k)//多重背包,二进制(该种物品指定上限)
{
if(p*k>=V) {//该种物品足以塞满背包-->转化为完全背包
CompletePack(p,w);
return ;
}
/*二进制思想拆分:多重背包中的一个物品--变成-->0-1背包中的多个物品
容量:2^0 2^1 2^2 2^k m-∑前面 ***保证k达到最大值
价值:2^0*c 2^1*c 2^2*c 2^k*c (m-∑前面 )*c
*/
else {
int kk= 1;
while(kk<=k) {
ZeroOnePack(kk*p,kk*w);
k = k - kk;
kk = kk<<1;
}
ZeroOnePack(k*p,k*w);
}
}
int main()
{
int T,i,j;
scanf("%d",&T);
while(T--) {
scanf("%d%d",&n,&V);//n物品种数
memset(dp,0,sizeof(dp));
for(i=1; i<=n; i++) {
scanf("%lld %lld %lld",&k[i],&p[i],&w[i]);
}
for(i=1; i<=n; i++) {
MultiplePack(p[i],w[i],k[i]);
}
printf("%lld\n",dp[V]);
}
return 0;
}