多重背包 单调队列优化

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;
}

我的视频题解空间

posted on   itdef  阅读(15)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2023-06-13 papamelon 245. 征募 Conscription(挑战程序设计竞赛)
2020-06-13 Leetcode 070 爬楼梯 动态规划
2018-06-13 20180613更新 leetcode刷题

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

点击右上角即可分享
微信分享提示