数位背包-梦幻岛宝珠
题目
在 $n(0\leq n \leq 100)$ 个物品中,选择重量不超过 $W(1\leq W \leq 2^{30})$ 的物品,是所选物品的总价值最大.
物品的重量 $w_i$ 可以写成 $a \times 2^{b} (1\leq a \leq 10,0\leq b \leq 30)$.
物品的价值 $v_i(1\leq v_i \leq 2^{30})$.
思路
通过 $w_i$ 可以写成 $a \times 2^{b} (1\leq a \leq 10,0\leq b \leq 30)$ ,很容易想到通过 $b$ 分层做, 同一层之间的合并是非常简单的01背包.
当前层转移到下一层是这道题的难点.
定义 $f_{ij}$ 表示背包剩余的容量为 $j \times 2^i$ 时的最大价值.
观察 $a \times 2^{i+1}$ 与 $a \times 2^ i$ 它们属于不同的两层, $a \times 2^{i+1}$ 可以写成 $2 \times a \times 2^i$ 这表示了 $f[i][2a] = f[i+1][a]$ 它们表示的容量相同.
接下来考虑总重量 $W$ 在层与层之间转移的限制.
我们从高位枚举 $W$ 时, $W$ 的第 $i$ 位为 1 时,转移到第 $i$ 层的状态为 $2 \times a + 1$ ,第 $i$ 位为 0 时, 转移到第 $i$ 层的状态为 $2 \times a + 0$.
第 $i$ 层 从第 $i+1$ 层转移过来要加上 $W$ 自身的容量, $W$ 的第 $i$ 位为 1 时要加上 $2^i$.
每一层在最坏情况下物品重量和不超过 1000 ,当转移过来的容量大于 1000 时就没必要保存了,因为剩余 $1000 \times 2^i$是可以把剩下的物品都取完的.
1 |
|
因为是从高位开始枚举的,会存在许多不合法的状态,令初值全部为负无穷,f[31][0] = 0.
答案为f[0][0],背包没有剩余空间的最大值.
可以通过滚动数组优化掉 $i$ .
代码
1 |
|