SDUT 3131-(多重背包)

14 篇文章 0 订阅

题目描述

新年伊始,我飞瞅准机会要大赚一笔,于是我飞换了一个体积为V的背包。

 

现在有N种商品,每种商品有Mi件,可以带来的收益为Pi,体积为Vi

那么问题来了,在所装物品不超过V的前提下的最大收益是多少?

谁能快速的做帮我飞算出来,我飞就让谁出任UFO,迎娶高富帅,走上人生巅峰233。各位准Final巨巨加油啊。

输入

  第一行输入一个 T ,代表有 T(1 <= T <= 15) 组数据。

对于每一组数据:

第一行有两个整数N , V

接下里的N行,每行三个整数MiViPi

对于所有数据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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Rocky0429

一块也是爱

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值