【codevs 3269】混合背包

来源:互联网 发布:上海知柚网络公司市值 编辑:程序博客网 时间:2024/06/11 14:24

题目描述 Description
背包体积为V ,给出N个物品,每个物品占用体积为Vi,价值为Wi,每个物品要么至多取1件,要么至多取mi件(mi > 1) , 要么数量无限 , 在所装物品总体积不超过V的前提下所装物品的价值的和的最大值是多少?

输入描述 Input Description
第一行两个数N,V,下面N行每行三个数Vi,Wi,Mi表示每个物品的体积,价值与数量,Mi=1表示至多取一件,Mi>1表示至多取Mi件,Mi=-1表示数量无限

输出描述 Output Description
1个数Ans表示所装物品价值的最大值

样例输入 Sample Input
2 10

3 7 2

2 4 -1

样例输出 Sample Output
22

数据范围及提示 Data Size & Hint
对于100%的数据,V <= 200000 , N <= 200

根据物品数量的不同进行状态转移

#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int MAXN = 200005;int n,v,x,vi,wi;int ans = 0,dp[MAXN];void zopack(int vi,int wi){    for(int i = v - vi; i >= 0; i --)        dp[i + vi] = max(dp[i + vi],dp[i] + wi);    return;}void wqpack(int vi,int wi){    for(int i = 0; i <= v - vi; i ++)        dp[i + vi] = max(dp[i +  vi],dp[i] + wi);    return;}void dcpack(int vi,int wi,int x){    if(vi * x > v)  wqpack(vi,wi);    int now = 1;    while(now < x)    {        zopack(vi * now,wi * now);        x -= now;        now <<= 1;    }    zopack(vi * x,wi * x);    return;}int main(){    scanf("%d %d",&n,&v);    for(int i = 1; i <= n; i ++)    {        scanf("%d %d %d",&vi,&wi,&x);        if(x < 0) wqpack(vi,wi);        else    dcpack(vi,wi,x);    }    for(int i = 0; i <= v; i ++)        ans = max(ans,dp[i]);    printf("%d\n",ans);    return 0;   }
0 0
原创粉丝点击