单调队列优化多重背包
![](https://i-blog.csdnimg.cn/blog_migrate/2f18139a7179364ff2db1074f7af68cb.png)
#include<bits/stdc++.h>
using namespace std;
#define maxn 110
int n, m, v[maxn], w[maxn], s[maxn];
int f[maxn];
struct Goods{
int w, v;
};
vector<Goods>goods;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> v[i] >> w[i] >> s[i];
for (int k = 1; k <= s[i]; k *= 2){
s[i] -= k;
goods.push_back({ w[i] * k, v[i] * k });
}
if (s[i] > 0)goods.push_back({ s[i] * w[i], s[i] * v[i] });
}
//i 10件 1010 1件 2件 4件 3件
for (int i = 0; i <= goods.size(); i++){
for (int j = m; j >= goods[i].w; j--){
f[j] = max(f[j], f[j - goods[i].w] + goods[i].v);
}
}//o(m*n*logm)<(m*sigmas[i] 2000*1000*15)
/*for (int i = 1; i <= n; i++){
for (int j = 0; j <= m; j++){
for (int k = 0; k <= s[i]; k++){
if (j >= k*w[i])f[i - 1][j - w[i] * k] + v[i] * k;
}
}
}*/
cout << f[n] << "\n";
return 0;
}
![](https://i-blog.csdnimg.cn/blog_migrate/1c54b3bd9489146b81851e0272af4bb7.png)
![](https://i-blog.csdnimg.cn/blog_migrate/3df41bc0fcbcf29ba464b6c22a9c1324.png)
![](https://i-blog.csdnimg.cn/blog_migrate/0d5c40d1b102469a6b93e7ea7fe5324b.png)
#include<bits/stdc++.h>
using namespace std;
#define maxn 20010
int n, m, v[maxn], w[maxn], s[maxn];
int f[2][maxn];
struct Goods{
int w, v;
};
int q[maxn];
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++){
cin >> v[i] >> w[i] >> s[i];
}
for (int i = 1; i <= n; i++){
for (int r = 0; r <= v[i]; ++r){
int hh = 0, tt = 1;
for (int j = r; j <= m; j += v[i]){
while (hh <= tt&&j - q[hh] > s[i] * v[i])hh++;
while (hh <= tt&&f[(i - 1) & 1][q[tt]] + (j - q[tt]) / v[i] * w[i] <= f[(i - 1) & 1][j])--tt;
q[++tt] = j;
f[i & 1][j] = f[(i - 1) & 1][q[hh]] + (j - q[hh]) / v[i] * w[i];
}
}
}//O(n*m)
cout << f[n & 1][m] << "\n";
return 0;
}