动态规划 -- 多重背包问题Ⅱ
问题描述
有 $N$ 种物品和一个容量是 $V$ 的背包。
第 $i$ 种物品最多有 $s_i$ 件,每件体积是 $v_i$,价值是 $w_i$。
求解将哪些物品装入背包,可使物品体积总和不超过背包容量,且价值总和最大。
输出最大价值。
输入格式
第一行两个整数,$N,V$,用空格隔开,分别表示物品种数和背包容积。
接下来有 $N$ 行,每行三个整数 $v_i,w_i,s_i$,用空格隔开,分别表示第 $i$ 种物品的体积、价值和数量。
输出格式
输出一个整数,表示最大价值。
数据范围
$0 \lt N \le 1000$
$0 \lt V \le 2000$
$0 \lt v_i, w_i, s_i \le 2000$
提示:
本题考查多重背包的二进制优化方法。
输入样例
1 | 4 5 |
输出样例:
1 | 10 |
题目求解
相比于多重背包问题Ⅰ(详见动态规划 — 多重背包问题Ⅰ)来讲,这道题目的数据范围变大了,导致原来$O(n^3)$的算法求解超时,这道题目考察的是一种二进制拆分状态压缩的思想。
二进制拆分
先看一个简单的例子:问怎样用最少的数字使得这些数字能组合得到$0 \sim 7$之间的所有数字,最简单易想的方案是用$7$个$1$选或者不选就能表示这些数,但是这样拆分出来的份数太多了,和$Ⅰ$中转换成$01$背包解决问题的方案一致,复杂度仍然达到$O(n^3)$。$0 \sim 7$一共八种状态最少使用3个数字选或者不选来表示这些状态,我们可以使用一种二进制的拆分方法,即$1,2,4$这三个数来表示。假设需要表示$0 \sim s$之间的数,如果$s$不是$2^n-1$,比如说$s$是$10$,我们不可以将$10$拆成$1,2,4,8$,这样的话表示的数字范围是$0 \sim 15$,应该拆分为$1,2,4,3$,最后的$3$即为$10 - 1 - 2 - 4$,相当于有了一个$3$的偏移量。总的拆分份数为$ \lceil \log(s) \rceil $。
代码
1 |
|








