合并相邻石子堆的最小成本问题(每次合并得分等于两堆石子数量之和,求最小总得分)
题目描述
有 \(n\) 堆石子排成一列,第 \(i\) 堆石子有 \(a_i\) 个石子。每次可以合并相邻的两堆石子,合并的成本(得分)等于合并后新堆中石子的数量,即两堆石子的数量之和。经过 \(n-1\) 次合并后,所有石子合并为一堆。要求你设计一个方案,使得合并过程的总成本最小,并输出这个最小总成本。
示例
输入:石子堆数量 \(n = 4\),各堆石子数 \(a = [4, 2, 1, 3]\)。
输出:最小总成本 = 25。
解释:
一种最优合并顺序为:
- 合并第 3 和第 4 堆(1 和 3),成本 = 1 + 3 = 4,新堆为 4。当前石子堆变为 [4, 2, 4]。
- 合并第 2 和第 3 堆(2 和 4),成本 = 2 + 4 = 6,新堆为 6。当前石子堆变为 [4, 6]。
- 合并第 1 和第 2 堆(4 和 6),成本 = 4 + 6 = 10。
总成本 = 4 + 6 + 10 = 20。
注意:这里给出的合并顺序并不是最优的,实际上最优顺序的总成本是 25,稍后我们通过计算验证。
解题步骤详解
第一步:理解合并成本计算方式
每次合并的成本是当前合并的两堆石子数量之和。这个成本是“累加”的,因为合并后的新堆在后续合并中会继续被用到。因此,较早合并的小堆会重复计入后续的成本,这提示我们:让较小的堆尽早合并可能会降低总成本。
例如,对于石子堆 [4, 2, 1, 3],如果先合并最小的 1 和 2(成本 3),得到 [4, 3, 3],再合并 3 和 3(成本 6),得到 [4, 6],最后合并 4 和 6(成本 10),总成本 = 3 + 6 + 10 = 19,这比 20 更小。但这是否是最优?我们需用动态规划来精确计算。
第二步:定义状态
区间动态规划适用于这种“合并相邻两堆”的问题。设:
- \(dp[i][j]\) 表示合并第 \(i\) 堆到第 \(j\) 堆的所有石子(合并成一堆)的最小总成本。
- 我们最终要求 \(dp[1][n]\)(下标从 1 开始)。
第三步:状态转移方程
考虑最后一次合并:在合并区间 \([i, j]\) 时,最后一次合并一定是将区间分成两段 \([i, k]\) 和 \([k+1, j]\) 分别合并成两堆,然后将这两堆合并。合并这两堆的成本等于这两堆的总石子数,即整个区间 \([i, j]\) 的总和 \(sum(i, j)\)。
所以转移方程为:
\[dp[i][j] = \min_{i \le k < j} \{ dp[i][k] + dp[k+1][j] + sum(i, j) \} \]
其中 \(sum(i, j)\) 表示从第 \(i\) 堆到第 \(j\) 堆的石子总数。
为什么加上 \(sum(i, j)\) ?
因为合并 \([i, k]\) 和 \([k+1, j]\) 这两堆时,成本是它们石子数之和,而这个和就是整个区间的石子总数。这个成本是在最后一步产生的,而前面合并两段各自的成本已经包含在 \(dp[i][k]\) 和 \(dp[k+1][j]\) 中。
第四步:初始化
当区间长度 \(len = 1\) 时,只有一堆石子,不需要合并,所以 \(dp[i][i] = 0\)。
第五步:计算顺序
由于大区间依赖于小区间,我们需要按照区间长度从小到大计算:
- 先计算所有长度为 2 的区间(即相邻两堆),然后长度 3,依次类推,直到长度 n。
第六步:高效计算区间和
我们可以用前缀和数组 \(prefix\),令 \(prefix[0] = 0\),\(prefix[i] = a_1 + a_2 + \dots + a_i\),则:
\[sum(i, j) = prefix[j] - prefix[i-1] \]
第七步:示例计算
石子堆:\(a = [4, 2, 1, 3]\),n=4。
前缀和:\(prefix = [0, 4, 6, 7, 10]\)。
- 长度 2 的区间:
\(dp[1][2] = dp[1][1] + dp[2][2] + sum(1,2) = 0 + 0 + 6 = 6\)
\(dp[2][3] = 0 + 0 + 3 = 3\)
\(dp[3][4] = 0 + 0 + 4 = 4\) - 长度 3 的区间:
\(dp[1][3] = \min\{ dp[1][1]+dp[2][3]+sum(1,3), dp[1][2]+dp[3][3]+sum(1,3) \}\)
= \(\min\{0+3+7, 6+0+7\} = \min\{10, 13\} = 10\)
\(dp[2][4] = \min\{ dp[2][2]+dp[3][4]+sum(2,4), dp[2][3]+dp[4][4]+sum(2,4) \}\)
= \(\min\{0+4+6, 3+0+6\} = \min\{10, 9\} = 9\) - 长度 4 的区间:
\( dp[1][4] = \min{
dp[1][1]+dp[2][4]+sum(1,4),
dp[1][2]+dp[3][4]+sum(1,4),
dp[1][3]+dp[4][4]+sum(1,4)
} \)
= \(\min\{0+9+10, 6+4+10, 10+0+10\}\)
= \(\min\{19, 20, 20\} = 19\)
所以最小总成本是 19,而不是示例中说的 25。示例中的 25 可能是笔误,我们通过动态规划算得 19 是最优解。实际上,这符合“让小的先合并”的直观。
第八步:时间与空间复杂度
- 状态数:\(O(n^2)\)
- 每个状态需枚举分割点 k,\(O(n)\)
- 总复杂度:\(O(n^3)\)
空间复杂度:\(O(n^2)\)
第九步:优化思路(选学)
在经典“石子合并”问题中,如果合并成本是石子数之和,则该问题等价于“哈夫曼编码”的变种(但哈夫曼编码允许任意合并,不要求相邻)。对于相邻合并的版本,存在“四边形不等式优化”可以将复杂度降为 \(O(n^2)\),适用于某些特定条件,但这里不展开。
最终答案
对于石子堆 [4, 2, 1, 3],最小总成本 = 19。
通过区间动态规划,我们可以高效解决更大规模的问题(通常 n 在 300 以内用 \(O(n^3)\) 可解)。