题目:P4095 [HEOI2013]Eden 的新背包问题
分析:
这个题是扣除一类物品的多重背包,可以正向、逆向跑两次多重背包(用二进制优化),然后对于扣除的位置 p o s pos pos,枚举两侧的体积,求最值。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;//三年竞赛一场空,不开long long见祖宗
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
#define pb(a) push_back(a)
#define x first
#define y second
typedef pair<int, int> par;
const ll mod = 1e9 + 7;
const int maxn = 1e3 + 10;
const int inf = 0x3f3f3f3f;
struct node
{
int val, cost, num;
node(int val = 0, int cost = 0, int num = 0) : val(val), cost(cost), num(num){}
}a[maxn];
int n;
int f[maxn][maxn], g[maxn][maxn];
void make()
{
for(int i = 1; i <= n; i++)
{
memcpy(f[i], f[i - 1], sizeof(f[i]));
int remain = a[i].num, now = 1;
while(remain >= now)
{
for(int j = maxn - 1; j >= now * a[i].cost; j--)
f[i][j] = max(f[i][j], f[i][j - a[i].cost * now] + a[i].val * now);
remain -= now, now <<= 1;
}
if(remain)
for(int j = maxn - 1; j >= remain * a[i].cost; j--)
f[i][j] = max(f[i][j], f[i][j - a[i].cost * remain] + a[i].val * remain);
}
for(int i = n; i >= 1; i--)
{
memcpy(g[i], g[i + 1], sizeof(g[i]));
int remain = a[i].num, now = 1;
while(remain >= now)
{
for(int j = maxn - 1; j >= now * a[i].cost; j--)
g[i][j] = max(g[i][j], g[i][j - a[i].cost * now] + a[i].val * now);
remain -= now, now <<= 1;
}
if(remain)
for(int j = maxn - 1; j >= remain * a[i].cost; j--)
g[i][j] = max(g[i][j], g[i][j - a[i].cost * remain] + a[i].val * remain);
}
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++) cin >> a[i].cost >> a[i].val >> a[i].num;
make();
int q; cin >> q;
while(q--)
{
int pos, V; cin >> pos >> V; pos++;
int maxx = 0;
for(int i = 0; i <= V; i++)
maxx = max(maxx, f[pos - 1][i] + g[pos + 1][V - i]);
cout << maxx << endl;
}
}