合并相邻石子堆的最大总得分问题(每次合并得分等于两堆石子数量之和的立方,求最大总得分)
题目描述
有 \(n\) 堆石子排成一列,第 \(i\) 堆石子有 \(a_i\) 个。每次操作可以合并相邻的两堆石子,合并后新的一堆石子数量为原来两堆石子数量之和,并得到得分,得分为两堆石子数量之和的立方。不断合并,直到只剩一堆石子。求可以获得的最大总得分。
示例(假设石子堆为 [1, 2, 3]):
- 先合并 1 和 2,新堆为 3(得分 = (1+2)^3 = 27),当前石子堆为 [3, 3]。
- 再合并 3 和 3,新堆为 6(得分 = (3+3)^3 = 216),总得分 = 27 + 216 = 243。
- 如果先合并 2 和 3,新堆为 5(得分 = 125),当前石子堆为 [1, 5]。
- 再合并 1 和 5,新堆为 6(得分 = 216),总得分 = 125 + 216 = 341。
可见不同的合并顺序会导致不同的总得分,目标是最大化总得分。
数据范围:
石子堆数 \(1 \le n \le 100\)(常见范围),每堆石子数量 \(1 \le a_i \le 100\)。
解题思路
1. 区间动态规划(区间DP)适用性
本题中,石子是线性排列的,每次合并相邻两堆,最终将所有石子合并为一堆。合并顺序决定了最终总得分,这是经典的“合并类”区间DP问题(类似于“石子合并”的标准问题,但得分计算不同)。
为什么可以用区间DP?
- 每次合并相邻两堆,相当于将某个区间 \([l, r]\) 内的所有石子合并为一堆,最后一步合并时是将区间分成两个子区间 \([l, k]\) 和 \([k+1, r]\) 各自合并得到的两堆再合并。
- 子问题之间独立:区间 \([l, r]\) 合并为一堆的最大得分,只依赖于其子区间合并的最大得分,以及最后一步合并的得分。
2. 定义状态
设 \(dp[l][r]\) 表示将区间 \([l, r]\) 内的所有石子合并为一堆所能获得的最大总得分(注意:这里的“总得分”指的是在该区间内部进行所有合并操作所得到的总分,不包括区间之外的合并)。
区间和:为方便计算最后一步合并的得分,我们需要知道区间内石子总数量。设 \(sum[l][r]\) 表示区间 \([l, r]\) 的石子总数量。可以用前缀和快速计算:
\(S[i] = a_1 + a_2 + ... + a_i\)(前缀和),则 \(sum[l][r] = S[r] - S[l-1]\)。
3. 状态转移方程
考虑区间 \([l, r]\) 如何合并为一堆:
最后一步一定是将区间分成左右两部分 \([l, k]\) 和 \([k+1, r]\) 分别合并成两堆,然后将这两堆合并。这一步合并的得分为:
\[\left( sum[l][r] \right)^3 \]
因为合并时两堆的石子数分别为 \(sum[l][k]\) 和 \(sum[k+1][r]\),而它们的和就是 \(sum[l][r]\)。
得分函数是立方,所以是 \((sum[l][r])^3\)。注意:合并得分只取决于两堆石子总数,和之前如何合并无关。
那么,区间 \([l, r]\) 的最大总得分 = 左子区间最大得分 + 右子区间最大得分 + 最后一步合并得分:
\[dp[l][r] = \max_{k = l}^{r-1} \left( dp[l][k] + dp[k+1][r] + (sum[l][r])^3 \right) \]
边界条件:当区间长度为 1 时(即 \(l = r\)),只有一堆石子,不需要合并,得分为 0。所以:
\[dp[l][l] = 0 \]
4. 计算顺序
区间DP通常按照区间长度从小到大计算:
- 长度 \(len = 1\):\(dp[l][l] = 0\)
- 长度 \(len = 2\) 到 \(n\):
- 遍历起点 \(l = 1\) 到 \(n-len+1\),计算终点 \(r = l+len-1\)
- 对于每个 \([l, r]\),遍历分界点 \(k = l\) 到 \(r-1\),更新 \(dp[l][r]\)
5. 最终答案
整个序列为 \([1, n]\),所以最大总得分是 \(dp[1][n]\)。
具体例子
石子堆:\(a = [1, 2, 3]\),前缀和 \(S = [0, 1, 3, 6]\)(下标从1开始,S[0]=0)。
计算过程:
- 初始化 \(dp[l][l] = 0\)。
- 长度 len=2:
- [1,2]:\(sum=3\),\(dp[1][2] = dp[1][1]+dp[2][2]+3^3 = 0+0+27=27\)
- [2,3]:\(sum=5\),\(dp[2][3] = 0+0+125=125\)
- 长度 len=3:
- [1,3]:\(sum=6\),分界点 k=1 或 2
- k=1:左[1,1]右[2,3]:0 + 125 + 6^3 = 0+125+216=341
- k=2:左[1,2]右[3,3]:27 + 0 + 216 = 243
最大值是 341。
- [1,3]:\(sum=6\),分界点 k=1 或 2
答案:341。
算法复杂度
- 状态数:\(O(n^2)\)
- 每个状态转移枚举分界点:\(O(n)\)
- 总时间复杂度:\(O(n^3)\),在 \(n \le 100\) 时可行。
- 空间复杂度:\(O(n^2)\) 用于 dp 数组和前缀和。
关键点总结
- 得分计算是立方:合并最后两堆时,得分是两堆总数之和的立方,即 \((sum[l][r])^3\)。
- 区间DP的标准框架:分治思想,枚举最后合并的分界点。
- 前缀和快速计算区间和:避免每次重复求和,提高效率。
这个题目是经典“石子合并”的一个变体,区别在于得分函数从“和”变成了“立方和”,但状态转移的结构完全相同,是区间DP的典型练习题。