zoukankan      html  css  js  c++  java
  • 单调队列优化版多重背包

    代码

    /*
    思路来源:
    f(i, j) = max(f(i - 1, j), f(i - 1, j - v) + w, f(i - 1, j - 2 * v) + 2 * w, ..., f(i - 1, j - s * v) + s * w)
    f(i, j - v) = max(         f(i - 1, j - v)    , f(i - 1, j - 2 * v) + w,          f(i - 1, j - s * v) + (s - 1) * w + f(i - 1, j - (s + 1) * v) + s * w)
    ......
    f(i, j - s * v) = max(f(i - 1, j - s * v), ...)
    这不就是窗口大小为 s 的滑动窗口吗
    */
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    
    using namespace std;
    
    const int N = 20010;
    
    int n, m;
    int f[N], g[N], q[N];
    
    int main()
    {
        scanf("%d%d", &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 j = 0; j < v; j ++) { // 序列的起点
                // f(0), f(0 + v), f(0 + 2 * v) + ...
                // f(1), f(1 + v), f(1 + 2 * v) + ...
                // f(j), f(j + v), f(j + 2 * v) + ...
                // 0 <= j < v
                int hh = 0, tt = -1;
                for(int k = j; k <= m; k += v) { // 枚举序列
                    // 序列下标是 j, j + v, j + 2 * v, ...
                    // 序列值为 f(j), f(j + v) - w, f(j + 2 * v) - 2 * w
                    // 当前枚举的下标是 k
                    if(hh <= tt && q[hh] < k - s * v) hh ++; 
                    // 上一步的含义是,因为窗口是从 k 往前 s 个元素,因此要判断是否在窗内
                    if(hh <= tt) f[k] = max(f[k], g[q[hh]] + (k - q[hh]) / v * w);
                    // 举个例子,f(i, j + s * v) = 
                    // = max(f(i - 1, j) + s * w, f(i - 1, j + v) + (s - 1) * w, ..., f(i - 1, j + s * v))
                    // = max(f(i - 1, j), f(i - 1, j + v) - w, ..., f(i - 1, j + s * v) - s * w) + s * w
                    while(hh <= tt && g[q[tt]] - (q[tt] - j) / v * w <= g[k] - (k - j) / v * w) tt --;
                    // 队列是单调递减的
                    q[++ tt] = k;
                }
            }
        }
        printf("%d
    ", f[m]);
        return 0;
    }
    
  • 相关阅读:
    Linux系统的关机、重启、睡眠
    Java 读写Properties配置文件
    Java识别操作系统
    Java DES 加解密("DES/CBC/PKCS5Padding")
    Java获取本机IP
    编写SHELL脚本--编写简单脚本
    配置yum软件仓库(redhat 7.0)
    简单的redis测试
    Seaslog安装和参数配置
    mac使用phpize进行安装的时候碰到的问题
  • 原文地址:https://www.cnblogs.com/miraclepbc/p/14460159.html
Copyright © 2011-2022 走看看