• acwing5. 多重背包问题 II


    有 N 种物品和一个容量是 V 的背包。

    第 i 种物品最多有 si 件,每件体积是 vi,价值是 wi。

    求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
    输出最大价值。

    输入格式

    第一行两个整数,N,V,用空格隔开,分别表示物品种数和背包容积。

    接下来有 N 行,每行三个整数 vi,wi,si,用空格隔开,分别表示第 i 种物品的体积、价值和数量。

    输出格式

    输出一个整数,表示最大价值。

    数据范围

    0<N≤1000
    0<V≤2000
    0<vi,wi,si≤2000

    提示:

    本题考查多重背包的二进制优化方法。

    输入样例

    4 5
    1 2 3
    2 4 1
    3 4 3
    4 5 2
    

    输出样例:

    10
    

    方法一:

    与上一题的多重背包问题题干相同,数据增加了一个数量级,说明要进行优化,否则会TLE。这里的做法是转化成01背包问题

    对于同一类物品,只要能列举出其[0, si]中的所有情况就可以了。假如转化为朴素01背包(在说了要用01背包来做之后,这个分法是最直接能想到的),做法是同类物品拆成多个,例如s=10,分成1 1 1 1 1 1 1 1 1 1,通过其选与不选来表示出[0, si]中的所有情况,但此时复杂度为O(n * v * s),复杂度数量级达到109。考虑二进制表示的方式,即用log(s)位数,就可以表示出[0, si]内任何数,例如s=10,只需要将物品分成1 2 4 3,通过对这几份物品进行选与不选,就可以表示出[0, 10]内的所有数字,再例如s=20,可以分成1 2 4 8 5。因此二进制表示的方式将复杂度优化为O(n * v * log(s))

    值得学习的地方在于这种二进制表示法,本质上可以用其它分法,只要能表示出[0, s]即可,但这种分法符合直觉,并且log的复杂度也会很低

    #include <bits/stdc++.h>
    
    using namespace std;
    
    
    typedef pair<int, int> PII;
    const int N = 2010;
    int n, v, f[N];
    vector<PII> obj;
    
    // 转化为朴素01背包:同种多件物品拆解成1 1 1 1...,复杂度O(N)
    // 转化为二进制01背包:同种多件物品拆解成1 2 4... 余数,复杂度O(logN)
    
    // 本质都是01背包,但拆解的方法可以表示[0, si]内的所有数字即可
    // by yxc
    
    int main() {
        int a, b, s;
    
        scanf("%d%d", &n ,&v);
        for (int i = 1; i <= n; ++i) {
            scanf("%d%d%d", &a, &b, &s);
            for (int j = 1; j <= s; j *= 2) {
                s -= j;
                obj.emplace_back(a*j, b*j);
            }
            if (s) obj.emplace_back(a*s, b*s);
        }
    
        for (auto o : obj) {
            for (int i = v; i >= o.first; i--) {
                f[i] = max(f[i], o.second + f[i-o.first]);
            }
        }
    
        printf("%d", f[v]);
    }
    
  • 相关阅读:
    Web开发中的显示与隐藏
    Html中的表格
    go标准库的学习-encoding/json
    go-simplejson文档学习
    go标准库的学习-regexp
    go标准库的学习-net
    go标准库的学习-strconv-字符串转换
    go标准库的学习-strings-字符串操作
    go标准库的学习-net/rpc
    go标准库的学习-net/rpc/jsonrpc
  • 原文地址:https://www.cnblogs.com/nosae/p/16003834.html
Copyright © 2020-2023  润新知