https://www.acwing.com/problem/content/6/
#include <iostream>
#include <memory.h>
#include <deque>
#include <stdio.h>
using namespace std;
/*
https://www.acwing.com/problem/content/6/
有 N种物品和一个容量是 V的背包。
第 i种物品最多有 si件,每件体积是 vi,价值是 wi。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,N,V (0<N≤1000, 0<V≤20000)
,用空格隔开,分别表示物品种数和背包容积。
接下来有 N行,每行三个整数 vi,wi,si
,用空格隔开,分别表示第 i种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
0<N≤1000
0<V≤20000
0<vi,wi,si≤20000
提示
本题考查多重背包的单调队列优化方法。
输入样例
4 5
1 2 3
2 4 1
3 4 3
4 5 2
输出样例:
10
*/
const int N = 20010;
int g[N], f[N];
int q[N];
int n, m;
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
int v, w, s;
cin >> v >> w >> s;
//f[]是当前dp g[]是上一次dp ,体积是索引
memcpy(g, f, sizeof f);
for (int j = 0; j < v; j++) {
int hh = 0; int tt = -1;
for (int k = j; k <= m; k += v) {
//本次的体积k 取s个物品 那么 最多需要f[k-s*v]的数据 比k-s*v小的体积 弹出队列
while (hh <= tt && k - s * v > q[hh]) hh++;
//得到f[k]的最大值
if (hh <= tt) f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w);
//排除无需在比较的体积v 为啥减去额外的w?
//自己做了修改 q[tt]和k在相同情况下比较决定是否弹出。 补上了两者v相差的额外w
while (hh <= tt && g[q[tt]] + (k- q[tt] ) / v * w < g[k] ) tt--;
q[++tt] = k;
}
}
}
cout << f[m] << endl;
return 0;
}
标签:www,背包,队列,int,hh,物品,include,单调
From: https://www.cnblogs.com/itdef/p/18246252