区间动态规划例题:石子合并的最小化最终方差问题
字数 4438 2025-12-20 01:13:10

区间动态规划例题:石子合并的最小化最终方差问题


题目描述

给定一个长度为 \(n\) 的数组 \(stones\),表示一排石子堆,每堆石子的重量为 \(stones[i]\)。你可以进行 \(n-1\) 次合并操作,每次合并相邻的两堆石子,合并的成本为这两堆石子的重量之和,合并后的新堆重量为两堆重量之和。目标是:经过所有合并操作后,只剩下一堆石子,最小化最终这堆石子的重量的方差(即最小化最终重量与某个目标值 \(T\) 的差的平方,但这里 \(T\) \) 是未知的,我们需要通过合并顺序来最小化最终重量的方差)。但题目可以简化表述为:
给定数组 \(stones\),合并相邻石子堆,每次合并成本为两堆重量和,最终得到一堆总重量为 \(S = \sum stones[i]\) 的石子。我们需要最小化合并过程中所有中间合并产生的“成本”的方差吗?不是,仔细澄清一下。

更准确的定义如下:
设合并过程中,每次合并时记录合并的两堆重量之和(即合并成本)。经过 \(n-1\) 次合并后,会得到一个长度为 \(n-1\) 的成本序列 \(c_1, c_2, \dots, c_{n-1}\)。最终总成本(即总耗费)是固定的,等于 \(S \times (n-1)\) 吗?不对,总成本是 \(\sum c_i\),而这个总成本实际上等于 \(S \times (n-1)\) 吗?我们需要推导。

实际上,每次合并的成本是合并的两堆重量之和,而每次合并后,新堆的重量会被后续合并多次计算。一个经典结论是:在相邻石子合并问题中,总合并成本 = 每堆石子的原始重量 × 该堆石子参与合并的次数。而这个“参与次数”取决于它被合并的时机。因此,总成本是固定的吗?不是,不同的合并顺序会导致不同的总成本。等等,这与我们熟知的“每次合并成本=两堆之和”的问题不同,经典问题是求最小总成本,而这里是求最小化最终重量的方差。让我们重新明确:

最终重量方差 的定义是:设最终合并得到的一堆石子重量为 \(W\)(显然 \(W = S\) 是固定的,因为不管怎么合并,总重量不会变),但方差是对“最终重量”而言的,而最终重量是固定的 \(S\),因此方差为0,这没有意义。
所以这里“方差”实际上是指合并过程中每一步合并得到的新堆重量的方差。即,每次合并后产生一个新堆,其重量是合并的两堆之和,我们需要记录这个新堆的重量,最终得到一个重量序列(长度为 \(n-1\)),然后计算这个序列的方差,并最小化这个方差。

但这样也不常见,常见的变形是:最小化合并过程中产生的最大合并成本(即最小化每一步合并的两堆之和的最大值),这可以用区间DP。但我们这里要求的是最小化合并成本序列的方差,即让合并过程尽量平稳,避免某次合并突然很大或很小。

为了让题目可解,我们明确为:

给定 \(stones[1..n]\),合并相邻石子堆,每次合并的成本 = 两堆重量之和,合并后新堆重量 = 两堆之和。记录每次合并的成本,得到一个成本序列 \(c_1, c_2, \dots, c_{n-1}\)。要最小化这个成本序列的方差,即

\[ > \text{方差} = \frac{1}{n-1} \sum_{i=1}^{n-1} (c_i - \bar{c})^2 > \]

其中 \(\bar{c}\) 是成本序列的平均值。注意 \(\sum c_i\) 并不是常数,因为不同的合并顺序会得到不同的总成本。


解题思路

方差 = \(E(c^2) - (E(c))^2\)
设总成本 \(T = \sum c_i\),平均值 \(\bar{c} = T/(n-1)\)
方差 = \(\frac{1}{n-1} \sum c_i^2 - \frac{T^2}{(n-1)^2}\)
因为 \(n\) 固定,所以最小化方差等价于最小化 \(\sum c_i^2\),因为 \(T^2\)\(T\) 的函数,而 \(T\) 是变化的,不能单独处理。但 \(T\) 实际上等于 \(\sum_{i=1}^n stones[i] \times (\text{该堆参与合并的次数})\),而“参与次数”等于该堆所在的合并区间在合并树中的深度。经典结论:总成本 \(T = \sum_{i=1}^n w_i \times (\text{该堆被合并的次数})\),且次数 = 该堆在合并树中到根的距离(叶子的深度)。不同的合并顺序对应不同的二叉树结构,叶子的深度不同,所以 \(T\) 可变。
因此,最小化方差需要同时考虑 \(\sum c_i^2\)\(T^2\),不能简单化为只最小化平方和。

但我们可以用DP状态记录 \(T\)\(\sum c_i^2\) 吗?复杂度太高。通常这类“最小化方差”问题,在区间DP中,我们可以用最小化每一步的平方和作为目标,因为方差与平方和、总和有关。但这里总成本 \(T\) 会变化,所以不能直接只最小化平方和。

不过,一个经典技巧是:方差最小化等价于最小化平方和,当平均值固定时。但这里平均值不固定,所以我们需要枚举可能的平均值?不可行。
另一种方法:方差 = \(\min_{a} \sum (c_i - a)^2 / (n-1)\),对固定的序列,当 \(a = \bar{c}\) 时取最小。所以我们的目标 = \(\min_{\text{合并顺序}} \min_{a} \sum (c_i - a)^2\)。交换次序:\(\min_{a} \min_{\text{合并顺序}} \sum (c_i - a)^2\)。对固定的 \(a\),我们可以定义一个新的成本:每次合并成本为两堆之和 \(c\),但贡献到目标函数的是 \((c-a)^2\)。这样就是一个新的区间DP问题:合并相邻石子,每次合并的代价为 \((c-a)^2\),求最小总代价。然后外层枚举 \(a\) 找到最小总代价。

\(a\) 是实数,不可枚举所有。注意到 \(c\) 是整数(石子重量整数),\(a\) 可以离散化到所有可能的合并成本值附近。但合并成本是连续的吗?不,合并成本是石子重量的和,是整数。所以 \(a\) 在整数附近枚举可能的最优值。但 \(a\) 的取值可能很多。更实际的是:我们观察到方差是凸函数,可以三分搜索 \(a\) 来找到最小方差。

算法步骤

  1. 计算前缀和 \(prefix\),方便快速得到区间和。
  2. 对于给定的参数 \(a\),定义 \(dp[i][j]\) 表示合并区间 \([i, j]\) 的石子成一堆时,最小的 \(\sum (c_k - a)^2\) 值,其中 \(c_k\) 是这个区间合并过程中每次合并的成本。
  3. 转移:最后一次合并是将 \([i, k]\)\([k+1, j]\) 两堆合并,成本为 \(sum(i,j)\)(区间和)。在此之前,左区间合并的代价和为 \(dp[i][k]\),右区间为 \(dp[k+1][j]\)。所以:

\[ dp[i][j] = \min_{i \le k < j} \{ dp[i][k] + dp[k+1][j] + (sum(i,j) - a)^2 \} \]

初始化:当 \(i=j\) 时,区间只有一堆,不需要合并,所以合并成本序列为空,\(dp[i][i] = 0\)
4. 最终答案 = \(dp[1][n]\) 对应这个 \(a\) 的最小平方偏差和。方差 = 这个值除以 \((n-1)\)
5. 外层三分搜索 \(a\) 在某个范围(如 \([0, S]\)),找到最小的 \(dp[1][n]\),然后得到最小方差。


细节与解释

  • 为什么可以这样定义 \(dp\)
    因为合并区间 \([i,j]\) 时,无论内部如何合并,最终这堆重量一定是 \(sum(i,j)\),且合并过程形成一棵二叉树,叶子的合并成本是树的内部节点的权值(左右子重量和)。这棵树的每个内部节点的权值为左右子树重量和,我们的目标是让这些节点权值与 \(a\) 的差的平方和最小。这正好是树形DP,但可以化作区间DP,因为合并顺序对应二叉树的结构,可以用区间DP枚举最后一次合并的分割点。

  • 时间复杂度
    区间DP本身 \(O(n^3)\),外层三分搜索 \(a\) 需要 \(O(\log (S/\epsilon))\) 次迭代,\(S\) 是总重量。所以总复杂度 \(O(n^3 \log S)\),在 \(n \le 100\) 时可行。

  • 边界
    \(a\) 的搜索范围是 \([0, S]\),因为每次合并成本至少是两堆最小和,最多是 \(S\),但实际 \(a\) 可能在平均值附近,取 \([0, S]\) 安全。

  • 实现注意
    DP 时用前缀和快速计算 \(sum(i,j)\)。三分搜索时比较 \(dp\) 值,取使 \(dp\) 最小的 \(a\)


举例说明

\(stones = [1, 2, 3]\)
总重量 \(S=6\)\(n=3\) 需要合并2次。
搜索 \(a\) 从0到6,比如 \(a=3\)

  • 区间[1,1]:dp=0,[2,2]:0,[3,3]:0。
  • 区间[1,2]:合并成本=1+2=3,平方偏差=(3-3)^2=0,dp=0+0+0=0。
  • 区间[2,3]:合并成本=5,平方偏差=4,dp=0+0+4=4。
  • 区间[1,3]:枚举k=1时,左[1,1]右[2,3],合并成本=6,平方偏差=9,总=0+4+9=13;k=2时,左[1,2]右[3,3],合并成本=6,平方偏差=9,总=0+0+9=9。取最小9。
    所以 \(a=3\) 时总平方偏差=9,方差=9/2=4.5。

尝试其他 \(a\) 找到更小的总平方偏差。


总结

这个问题的核心是:

  1. 将最小化方差转化为对参数 \(a\) 的最小化平方偏差和问题。
  2. 对每个 \(a\),用区间DP计算最小平方偏差和。
  3. 用三分搜索找到最优的 \(a\)

这样就能求出合并顺序,使得合并成本序列的方差最小,从而使合并过程更加平稳。

区间动态规划例题:石子合并的最小化最终方差问题 题目描述 给定一个长度为 \( n \) 的数组 \( stones \),表示一排石子堆,每堆石子的重量为 \( stones[ i] \)。你可以进行 \( n-1 \) 次合并操作,每次合并相邻的两堆石子,合并的成本为这两堆石子的重量之和,合并后的新堆重量为两堆重量之和。目标是:经过所有合并操作后,只剩下一堆石子, 最小化最终这堆石子的重量的方差 (即最小化最终重量与某个目标值 \( T \) 的差的平方,但这里 \( T \) \) 是未知的,我们需要通过合并顺序来最小化最终重量的方差)。但题目可以简化表述为: 给定数组 \( stones \),合并相邻石子堆,每次合并成本为两堆重量和,最终得到一堆总重量为 \( S = \sum stones[ i] \) 的石子。我们需要 最小化合并过程中所有中间合并产生的“成本”的方差 吗?不是,仔细澄清一下。 更准确的定义如下: 设合并过程中,每次合并时记录合并的两堆重量之和(即合并成本)。经过 \( n-1 \) 次合并后,会得到一个长度为 \( n-1 \) 的成本序列 \( c_ 1, c_ 2, \dots, c_ {n-1} \)。最终总成本(即总耗费)是固定的,等于 \( S \times (n-1) \) 吗?不对,总成本是 \( \sum c_ i \),而这个总成本实际上等于 \( S \times (n-1) \) 吗?我们需要推导。 实际上,每次合并的成本是合并的两堆重量之和,而每次合并后,新堆的重量会被后续合并多次计算。一个经典结论是:在相邻石子合并问题中, 总合并成本 = 每堆石子的原始重量 × 该堆石子参与合并的次数 。而这个“参与次数”取决于它被合并的时机。因此,总成本是固定的吗?不是,不同的合并顺序会导致不同的总成本。等等,这与我们熟知的“每次合并成本=两堆之和”的问题不同,经典问题是求最小总成本,而这里是求最小化最终重量的方差。让我们重新明确: 最终重量方差 的定义是:设最终合并得到的一堆石子重量为 \( W \)(显然 \( W = S \) 是固定的,因为不管怎么合并,总重量不会变),但方差是对“最终重量”而言的,而最终重量是固定的 \( S \),因此方差为0,这没有意义。 所以这里“方差”实际上是指 合并过程中每一步合并得到的新堆重量的方差 。即,每次合并后产生一个新堆,其重量是合并的两堆之和,我们需要记录这个新堆的重量,最终得到一个重量序列(长度为 \( n-1 \)),然后计算这个序列的方差,并最小化这个方差。 但这样也不常见,常见的变形是: 最小化合并过程中产生的最大合并成本 (即最小化每一步合并的两堆之和的最大值),这可以用区间DP。但我们这里要求的是 最小化合并成本序列的方差 ,即让合并过程尽量平稳,避免某次合并突然很大或很小。 为了让题目可解,我们明确为: 给定 \( stones[ 1..n] \),合并相邻石子堆,每次合并的成本 = 两堆重量之和,合并后新堆重量 = 两堆之和。记录每次合并的成本,得到一个成本序列 \( c_ 1, c_ 2, \dots, c_ {n-1} \)。要最小化这个成本序列的方差,即 \[ \text{方差} = \frac{1}{n-1} \sum_ {i=1}^{n-1} (c_ i - \bar{c})^2 \] 其中 \( \bar{c} \) 是成本序列的平均值。注意 \( \sum c_ i \) 并不是常数,因为不同的合并顺序会得到不同的总成本。 解题思路 方差 = \( E(c^2) - (E(c))^2 \)。 设总成本 \( T = \sum c_ i \),平均值 \( \bar{c} = T/(n-1) \)。 方差 = \( \frac{1}{n-1} \sum c_ i^2 - \frac{T^2}{(n-1)^2} \)。 因为 \( n \) 固定,所以最小化方差等价于最小化 \( \sum c_ i^2 \),因为 \( T^2 \) 是 \( T \) 的函数,而 \( T \) 是变化的,不能单独处理。但 \( T \) 实际上等于 \( \sum_ {i=1}^n stones[ i] \times (\text{该堆参与合并的次数}) \),而“参与次数”等于该堆所在的合并区间在合并树中的深度。经典结论:总成本 \( T = \sum_ {i=1}^n w_ i \times (\text{该堆被合并的次数}) \),且次数 = 该堆在合并树中到根的距离(叶子的深度)。不同的合并顺序对应不同的二叉树结构,叶子的深度不同,所以 \( T \) 可变。 因此,最小化方差需要同时考虑 \( \sum c_ i^2 \) 和 \( T^2 \),不能简单化为只最小化平方和。 但我们可以用DP状态记录 \( T \) 和 \( \sum c_ i^2 \) 吗?复杂度太高。通常这类“最小化方差”问题,在区间DP中,我们可以用 最小化每一步的平方和 作为目标,因为方差与平方和、总和有关。但这里总成本 \( T \) 会变化,所以不能直接只最小化平方和。 不过,一个经典技巧是:方差最小化等价于最小化平方和,当平均值固定时。但这里平均值不固定,所以我们需要枚举可能的平均值?不可行。 另一种方法:方差 = \( \min_ {a} \sum (c_ i - a)^2 / (n-1) \),对固定的序列,当 \( a = \bar{c} \) 时取最小。所以我们的目标 = \( \min_ {\text{合并顺序}} \min_ {a} \sum (c_ i - a)^2 \)。交换次序:\( \min_ {a} \min_ {\text{合并顺序}} \sum (c_ i - a)^2 \)。对固定的 \( a \),我们可以定义一个新的成本:每次合并成本为两堆之和 \( c \),但贡献到目标函数的是 \( (c-a)^2 \)。这样就是一个新的区间DP问题:合并相邻石子,每次合并的代价为 \( (c-a)^2 \),求最小总代价。然后外层枚举 \( a \) 找到最小总代价。 但 \( a \) 是实数,不可枚举所有。注意到 \( c \) 是整数(石子重量整数),\( a \) 可以离散化到所有可能的合并成本值附近。但合并成本是连续的吗?不,合并成本是石子重量的和,是整数。所以 \( a \) 在整数附近枚举可能的最优值。但 \( a \) 的取值可能很多。更实际的是:我们观察到方差是凸函数,可以三分搜索 \( a \) 来找到最小方差。 算法步骤 : 计算前缀和 \( prefix \),方便快速得到区间和。 对于给定的参数 \( a \),定义 \( dp[ i][ j] \) 表示合并区间 \([ i, j]\) 的石子成一堆时,最小的 \( \sum (c_ k - a)^2 \) 值,其中 \( c_ k \) 是这个区间合并过程中每次合并的成本。 转移:最后一次合并是将 \([ i, k]\) 和 \([ k+1, j]\) 两堆合并,成本为 \( sum(i,j) \)(区间和)。在此之前,左区间合并的代价和为 \( dp[ i][ k] \),右区间为 \( dp[ k+1][ j ] \)。所以: \[ dp[ i][ j] = \min_ {i \le k < j} \{ dp[ i][ k] + dp[ k+1][ j ] + (sum(i,j) - a)^2 \} \] 初始化:当 \( i=j \) 时,区间只有一堆,不需要合并,所以合并成本序列为空,\( dp[ i][ i ] = 0 \)。 最终答案 = \( dp[ 1][ n ] \) 对应这个 \( a \) 的最小平方偏差和。方差 = 这个值除以 \( (n-1) \)。 外层三分搜索 \( a \) 在某个范围(如 \([ 0, S]\)),找到最小的 \( dp[ 1][ n ] \),然后得到最小方差。 细节与解释 为什么可以这样定义 \( dp \) ? 因为合并区间 \([ i,j ]\) 时,无论内部如何合并,最终这堆重量一定是 \( sum(i,j) \),且合并过程形成一棵二叉树,叶子的合并成本是树的内部节点的权值(左右子重量和)。这棵树的每个内部节点的权值为左右子树重量和,我们的目标是让这些节点权值与 \( a \) 的差的平方和最小。这正好是树形DP,但可以化作区间DP,因为合并顺序对应二叉树的结构,可以用区间DP枚举最后一次合并的分割点。 时间复杂度 : 区间DP本身 \( O(n^3) \),外层三分搜索 \( a \) 需要 \( O(\log (S/\epsilon)) \) 次迭代,\( S \) 是总重量。所以总复杂度 \( O(n^3 \log S) \),在 \( n \le 100 \) 时可行。 边界 : \( a \) 的搜索范围是 \( [ 0, S] \),因为每次合并成本至少是两堆最小和,最多是 \( S \),但实际 \( a \) 可能在平均值附近,取 \( [ 0, S ] \) 安全。 实现注意 : DP 时用前缀和快速计算 \( sum(i,j) \)。三分搜索时比较 \( dp \) 值,取使 \( dp \) 最小的 \( a \)。 举例说明 设 \( stones = [ 1, 2, 3 ] \): 总重量 \( S=6 \),\( n=3 \) 需要合并2次。 搜索 \( a \) 从0到6,比如 \( a=3 \): 区间[ 1,1]:dp=0,[ 2,2]:0,[ 3,3 ]:0。 区间[ 1,2 ]:合并成本=1+2=3,平方偏差=(3-3)^2=0,dp=0+0+0=0。 区间[ 2,3 ]:合并成本=5,平方偏差=4,dp=0+0+4=4。 区间[ 1,3]:枚举k=1时,左[ 1,1]右[ 2,3],合并成本=6,平方偏差=9,总=0+4+9=13;k=2时,左[ 1,2]右[ 3,3 ],合并成本=6,平方偏差=9,总=0+0+9=9。取最小9。 所以 \( a=3 \) 时总平方偏差=9,方差=9/2=4.5。 尝试其他 \( a \) 找到更小的总平方偏差。 总结 这个问题的核心是: 将最小化方差转化为对参数 \( a \) 的最小化平方偏差和问题。 对每个 \( a \),用区间DP计算最小平方偏差和。 用三分搜索找到最优的 \( a \)。 这样就能求出合并顺序,使得合并成本序列的方差最小,从而使合并过程更加平稳。