「比赛记录」AtCoder abc373 (9.28)
CTH 想看 F 题解,于是先发出来
F.Knapsack with Diminishing Values
属于是翻译官方题解了
首先我们设 \(dp_{w,j}\) 表示从权重为 \(w\) 或更小的物品中选总重为 \(j\) 的物品可以得到的最大幸福度。
考虑 \(dp\) 的转移。
我们把所有物品按照权重 \(w\) 分为多组,(每一组中所有物品的 \(w\) 相同,但 \(v\) 可能不同),设 \(f_{w,k}\) 表示从单个物品重为 \(w\) 的组中选出 \(k\) 个物品的最大幸福度。
假设我们已经知道 \(f_{w,k}\),那么可以得到 \(dp\) 的转移如下:(\(W\) 为题目中的 \(W\))
\[dp_{w,j}=dp_{w-1,j-kw}+f_{w,k}\ \ (k\in [\ 0,\lfloor \frac{j}{w}\rfloor \ ], j\in [\ 0,W\ ])
\]
那么这道题便做出来了,现在我们需要做的就是考虑如何求 \(f_{w,k}\) ,可以用一种贪心的策略。
首先我们需要知道:\(k\times v-k^2 = \sum_{i=1}^{k} (v-2i+1)\),式子好推,但这是关键。
有了这个式子,我们可以理解为第一次使用一种物品 \(i\) 会有 \(v_i-1\) 的贡献,之后再使用一次每次的贡献就会减少 \(2\),即第 \(j\) 次使用物品 \(i\) 会有 \(v_i-1-2(j-1)\) 的贡献。
所以对于同一组即权重都为 \(w\) 的物品,最开始先用一个优先队列维护所有不同种物品的 \(v_i-1\),每次肯定优先使用队列顶端的所表示物品,并且更新队列,大概就是以下三种操作:
-
取出队列顶 \(d\) 为现在改组所有物品中可以提供的最大贡献。
-
更新 \(f_{w,k}\),\(f_{w,k} = f_{w,k-1}+d\);
-
更新队列,其实就是将 \(d-2\) 再次入队。