P1776 宝物筛选_NOI导刊2010提高(02)&& 多重背包二进制优化

多重背包, 要求 \(N\log N\) 复杂度

Solution

众所周和, \(1-N\) 之内的任何数可以由 \(2^{0}, 2^{1}, 2^{2} ... 2^{\log N}, N - 2^{\log N}\) 拼凑而成
我们知道一定有一种最优方案, 使得第 \(i\) 种物品只消耗 \(x\)\((x <= n_{i})\)
\(x\) 可以被二进制凑出来
所以我们先二进制拆分物品件数, 再跑 \(01\) 背包即可

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

板题

Code

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<climits>
#define LL long long
using namespace std;
LL RD(){
    LL out = 0,flag = 1;char c = getchar();
    while(c < '0' || c >'9'){if(c == '-')flag = -1;c = getchar();}
    while(c >= '0' && c <= '9'){out = out * 10 + c - '0';c = getchar();}
    return flag * out;
    }
const LL maxn = 2000019;
LL num, V;
LL v[maxn], w[maxn], cnt;
LL dp[maxn];
int main(){
	num = RD(), V = RD();
	for(LL i = 1;i <= num;i++){
		LL val = RD(), wei = RD(), n = RD(), t = 1;
		while(n >= t){
			v[++cnt] = val * t, w[cnt] = wei * t;
			n -= t;
			t <<= 1;
			}
		v[++cnt] = val * n, w[cnt] = wei * n;
		}
	for(LL i = 1;i <= cnt;i++){
		for(LL j = V;j >= w[i];j--){
			dp[j] = max(dp[j], dp[j - w[i]] + v[i]);
			}
		}
	printf("%lld\n", dp[V]);
	return 0;
	}
posted @ 2018-09-12 22:21  Tony_Double_Sky  阅读(144)  评论(0)    收藏  举报