「POJ 3666」Making the Grade - 线性 DP
题意描述
给定一个长度为 \(N\) 的序列 \(A\),要求构造一个长度为 \(N\) 的序列 \(B\)。\(B\) 满足以下条件:
\(B\) 非严格单调(单调递增或单调递减都可),
在满足 \(1\) 的条件下,使 \(S = \sum_{i = 1}^{N} | A_i - B_i |\)。
仅需求出最小值 \(S\) 即可。题目数据满足 \(1 \leq N \leq 2000\)。
解题思路
首先我们讨论 \(B\) 为非严格单调序列。非严格单调递减同理。两者取最小值即使答案。
构造处理
首先我们提出一个猜想:至少有一种构造方法,满足在 \(S\) 最小的情况下,使 \(B\) 中所有数字均在 \(A\) 中出现过。
这个猜想可以用数学归纳法进行证明:
显然在 \(N = 1\) 的时候该结论成立。
设该猜想对于 \(N = x - 1\) 时成立,则对于 \(N = x\),分为一下情况:
\(B_{x - 1} \leq A_x\),显然 \(B_{x} = A_x\) 的时候 \(S\) 最小。
\(B_{x - 1} > A_x\),可令 \(B_x = B_{x - 1}\),或者寻找一个值 \(y\),将 \(B_y, B_{y + 1}, B_{y + 2}, \cdots, B_x\) 赋值为同一个数 \(z\)。令 \(A\) 的中位数为 \(mid\),若 \(mid < B_{y - 1}\),则 \(z = B_{y - 1}\),否则 \(z = mid\)。从中位数性质易得该结论。
动态规划
接下来即可进行动态规划。令排序过的 \(A\) 为 \(S\),我们可以设数组 \(f_{i, j}\),其中 \(i\) 表示目标是求 \(B\) 的第 \(i\) 项,\(j\) 表示 \(B_i = S_j\) 的情况。\(f_{i, j}\) 的值表示 \(A\) 在 \(i\) 及之前的序列在使用 \(S\) 在 \(j\) 及以前的序列的数的情况下 \(S\) 的最小值。我们可以推出下列状态转移方程:
\[ f_{i, j} = \min \limits_{1 \leq k \leq j} \{ f_{i - 1, k} + |A_i - S_j| \} \]
初始状态为 \(f = INF\),目标所求为 \(\min \limits_{1 \leq i \leq n} f_{n, i}\)。
由于状态转移方程中 \(f_{i - 1, k}\) 的最小值滚动时只会受到最后一个数的影响,我们可以将前一个最小值存起来,更新时仅比较前一个最小值和 \(f_{i - 1, k}\)。可以将时间复杂度从 \(O(n^3)\) 优化到 \(O(n^2)\)。
代码演示
1 |
|