Loading

[总结] 基于贪心和有效状态数分析的大体积背包问题

例1

背包为容量 \(m\)\(n\) 种物品,第 \(i\) 种体积 \(a_i\),价值 \(b_i\),数量无限,求不超过背包容量的前提下能获得的最大价值。

\(n\le 10^6,m\le 10^{16},a_i,b_i\le 100\)

首先有效物品其实不超过 100 件,不妨认为 \(n\le 100\)

然后我们需要一个引理:给定任意 \(n\) 个整数,它们之中存在若干个整数的和为 \(n\) 的倍数。

证明:

\(n\) 个数为 \(a_1,a_2,a_3,\cdots,a_n\)\(S_i=\sum\limits_{j=1}^i a_i\).

\(S_0,S_1,S_2\cdots,S_n\)\(n+1\) 个数,至少有两个同余 \(n\),即对应了一段 \(a_i\) 之和是 \(n\) 的倍数。

那么假设全局性价比最高的物品体积为 \(a_s\),则存在一种最优方案满足其他所有物品的个数之和小于 \(a_s\)

否则,存在若干物品体积之和为 \(a_s\) 的倍数,替换成 \(a_s\) 一定不劣。

那么直接选 \(\lfloor\frac{m}{a_s}\rfloor-a_s\) 件性价比最高的物品,剩下的空间做完全背包即可,复杂度 \(O(a^3)\)

例2

\(2m+1\) 种物品,重量分别为 \(-m,-m+1,\cdots,m-1,m\)。重量为 \(i\) 的物品有 \(a_i\) 个。

求在重量恰好为 \(L\) 的前提下,最多能拿多少物品。

\(1\le m\le300,-10^{18}\le L\le 10^{18},0\le a_i\le 10^{12}\)

首先考虑一些简单的处理:

  • 比如重量为 \(0\) 可以在过程中忽略,最后加上。
  • 预先选上所有重量为负的物品,则再选择时,物品的含义就变了,重量为负的物品相当于重量为正,价值为负。

在贪心的前提下,我们尽量逼近 \(L\),也就是说,按照 \(1,2,3,\cdots,m,-m,-m+1,\cdots, -1\) 的顺序,能选就选。

然后接下来考虑如何调整为恰好是 \(L\),那么在有解的情况下,此时的重量与 \(L\) 的差显然属于 \([0,m]\),记为 \(D\)

设此时答案物品集合为 \(S_0\),还未选择的物品集合是 \(S_1\)

那么调整过程一定是从 \(S_0\) 中拿出某些物品放入 \(S_1\),将 \(S_1\) 中的某些物品放入 \(S_0\)

不妨将一个物品所属集合的变化看作一次调整,那么单次调整对于总重量的影响一定属于 \([-m,m]\)

则我们可以证明一定存在一种方案使得调整次数不超过 \(2m+1\)

证明:

对于一种调整方案,存在一种排列方式,使得所有前缀和都属于 \([-m,m]\)

假设现在的前缀和为 \(s\)

  • \(s\ge 0\),因为最终总和属于 \([0,m]\),则要么能选出一个负数,要么能选出一个正数,与 \(s\) 相加不超过 \(m\)
  • \(s<0\),同理一定能选出一个正数接在后面。

则前缀和总最多只有 \(2m+1\) 种,而前缀和相同的两个位置,中间一段的调整都是无意义的,故得证。

那么调整次数是 \(O(m)\) 级别,单次重量变化也是 \(O(m)\) 级别,如不考虑顺序,过程中的重量变化即为 \(O(m^2)\) 级别。

不妨设 \(f_i\) 表示 \(S_0\) 中选出重量为 \(i\) 的物品,最少减少的物品数量,\(g_i\) 表示 \(S_1\) 中选出重量为 \(i\) 的物品,最多增加的物品数量,那么最优答案对应的调整方案就是 \(\max f_i+g_{i+D}\)

那么直接二进制分组优化多重背包即可在 \(O(m^3\log m)\) 的复杂度解决问题。

分析

试图从两个题目寻找共性。

其实本质上都是贪心+调整,所以重点是就是找到合理的贪心策略,以及分析调整的有效性,得出最小的必要范围。

posted @ 2022-07-12 11:35  IrisT  阅读(72)  评论(0编辑  收藏  举报