AcWing 6. 多重背包问题 III
原题链接
困难
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
const int M = 20010, N = 1010;
int f[M], g[M];
int n, m;
int que[M];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++)
{
int v, w, s;
scanf("%d%d%d", &v, &w, &s);
memcpy (g, f, sizeof f);
for (int r = 0; r < v; r ++)
{
int head = 0, tail = -1;
for (int k = 0; r + k*v <= m; k ++)
{
if(head <= tail && k - que[head] > s) head ++;// quehead in window or not
while(head <= tail && g[r + k*v] - k*w >= g[r + que[tail]*v] - que[tail]*w) tail --;
// 这一步弹出tail的操作很机智:(设j=a+bv)
// 想要比较g[r+kv]+(b-k)w, g[r+que[tail]v]+(b-que[tail)w
// 可以自然地将bw消去,等价于比较g[r+kv]-kw, g[r+que[tail]v]-que[tail]w
// 啊。。。终于弄懂了,太开心了😁
que[++ tail] = k;
f[r + k*v] = g[r + que[head]*v] + (k - que[head]) * w;
}
}
}
cout << f[m] << endl;
return 0;
}