luogu P1776 宝物筛选_NOI导刊2010提高(02)

一道多重背包问题

多重背包就是

有n种物品,每种物品有各自的价值和体积,并每种物品有一定数目

给你一个体积v的背包,求最大价值

我们可以想到把多重背包分解成01背包来做

复杂度仍然很高

那我们想到了某种优化(谁想到的???反正不是我

每个数都可以用二进制来表示,则每个数都可以拆成2的次方的和

如 18 = 1 + 2 + 4 + 8 + 3(2 + 1)

而这几个拆出来的数可以组合成18以内的任何数(不信试试鸭

这样我们可以把多重背包内的每个物品,拆成1,2,4,8……

一下子就降低了复杂度对吧

然后来看看题面

哇多重背包!

为什么不多进去几次全都拿出来啊好zz

 emmmm

那我们看代码实现吧

#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 10000010//不知道拆成几个所以数组开大一点

int f[maxn],v[maxn],w[maxn];
int cnt;

int main() {
    int n,W,cnt = 0;
    scanf("%d%d",&n,&W);
    for(int i = 1; i <= n; i++) {
        int value,weight,num;
        scanf("%d%d%d",&value,&weight,&num);
        for(int j = 1; j <= num; j <<= 1) {
            v[++cnt] = j * value;
            w[cnt] = j * weight;
            num -= j;//把物品拆开的操作
        }
        if(num) {
            v[++cnt] = value * num;
            w[cnt] = weight * num;
        }
    }
    for(int i = 1; i <= cnt; i++)
        for(int j = W; j >= w[i]; j--) {
            f[j] = max(f[j],f[j - w[i]] + v[i]);//变成01背包~
        }
    printf("%d",f[W]);
    return 0;
}

好啦

这次不是特别水吧www

猜你喜欢

转载自www.cnblogs.com/sevenyuanluo/p/10295988.html