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