多重背包模板题
#include <iostream>
#include <cstring>
using namespace std;
const int N = 505, M = 6005;
int n, m, v, w, s, f[M], g[M];
int que[M], head, tail; //队列存的元素是下标(体积),即f[i][j]的j
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i ++) {
scanf("%d%d%d", &v, &w, &s);
memcpy(g, f, sizeof(f));
for (int j = 0; j < v; j ++) {
head = 0, tail = -1;
for (int k = j; k <= m; k += v) {
// 队列不为空,且队头下标在窗口外,队头出队
if (head <= tail && que[head] < k - s * v) head++;
// 进队,考虑不同项加的w个数不同
while (head <= tail &&
g[k] >= g[que[tail]] + (k - que[tail]) / v * w) tail --;
que[++ tail] = k;
// 更新f[i][k]
if (head <= tail) {
f[k] = max(f[k], g[que[head]] + (k - que[head]) / v * w);
}
}
}
}
printf("%d\n", f[m]);
}