codevs3269 混合背包 x

3269 混合背包

 时间限制: 1 s
 空间限制: 256000 KB
 题目等级 : 钻石 Diamond
 
题目描述 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

思路:
  背包九讲之大集合!
坑点:
  有的是正序枚举(完全背包是正序枚举),有的是逆序枚举(01背包)
上代码:
 
1)全T代码(之样例都是骗人的):
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

const int M = 2e5 + 1;
const int N = 201;
int V,n;
int dp[M];

struct Bag {
    int v,w,m;
}t[N];

int main()
{
    scanf("%d%d",&n,&V);
    for(int i=1,v,w,m;i<=n;i++)
    {
        scanf("%d%d%d",&v,&w,&m);
        if(m==-1) m=V/v;
        t[i].v=v,t[i].w=w,t[i].m=m;
    }
    for(int i=1,mi,vi,wi;i<=n;i++)
    {
        mi=t[i].m,vi=t[i].v,wi=t[i].w;
        for(int k=1;k<=mi;k++)
            for(int j=V;j>=k*vi;j--)
                dp[j]=max(dp[j],dp[j-k*vi]+k*wi);
    }
    printf("%d",dp[V]);
    return 0;
}

2)正解

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;

const int M = 2e5 + 1;
const int N = 201;
int V,n;
int dp[M];

inline void zeroonebag(int v,int w) {
    for(int i=V;i>=v;i--)
        dp[i]=max(dp[i],dp[i-v]+w);
}

inline void completebag(int v,int w) {
    for(int i=v;i<=V;i++)
        dp[i]=max(dp[i],dp[i-v]+w);
}

inline void multibag(int v,int w,int m) {
    if(v*m>=V) {
        completebag(v,w);
        return;
    }
    int k=1;
    while(k<=m)
    {
        zeroonebag(k*v,k*w);
        m-=k;
        k<<=1;///等价于*2
    }
    zeroonebag(m*v,m*w);
}

int main()
{
    scanf("%d%d",&n,&V);
    for(int i=1,v,w,m;i<=n;i++)
    {
        scanf("%d%d%d",&v,&w,&m);
        if(m==1) 
            zeroonebag(v,w);
        else
            if(m==-1) 
                completebag(v,w);
        else
            multibag(v,w,m);
    }
    printf("%d",dp[V]);
    return 0;
}

 

posted @ 2017-07-13 10:24  夜雨声不烦  阅读(130)  评论(0编辑  收藏  举报