最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

AcWing.7 混合背包问题

来源:博客园


【资料图】

题目描述

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

物品一共有三类:

  • 第一类物品只能用1次(01背包);
  • 第二类物品可以用无限次(完全背包);
  • 第三类物品最多只能用 \(s_i\) 次(多重背包);

每种体积是 \(v_i\),价值是 \(w_i\)。

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

解题思路

\(\qquad\)由于多重背包经过二进制拆分之后会变成以\(2^k\)为数量的\(log_2{s_i}\)堆,我们可以在这些堆上做\(01\)背包,所以我们就把这个混合背包搞成了两类:

\(\qquad\)\(a.s_{i}=0\),此时在题目的描述中是完全背包,做一遍完全就行。

\(\qquad\)\(b.s_{i}\neq 0\)此时我们就是\(01\)或者多重了,那\(01\)我们可以看成是每个物品最多用\(1\)次,也就是所有的\(s_i\)都是\(1\),然后做二进制优化的多重背包即可

代码

#include using namespace std;const int N = 1010;int f[N], n, m;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);                if (s == 0) //当完全背包做        {            for (int j = v; j <= m; j ++ )                 f[j] = max(f[j], f[j - v] + w);        }        else //转化为01背包        {            if (s == -1) s = 1;                        for (int k = 1; k <= s; k <<= 1)             {                for (int j = m; j >= v * k; j -- )                     f[j] = max(f[j], f[j - v * k] + w * k);                s -= k;            }                        if (s) for (int j = m; j >= s * v; j -- )                f[j] = max(f[j], f[j - v * s] + w * s);        }    }        printf("%d\n", f[m]);        return 0;}

\(\color{Green}{顺利AC!}\)

关键词: 我们就是 背包问题 就把这个