环形石子合并(最大得分)问题
题目描述:有 N 堆石子排成一个环形,第 i 堆石子有 a[i] 个。现在要将这 N 堆石子合并成一堆,合并的规则是每次只能合并相邻的两堆石子,合并的得分是新一堆石子的总数。目标是求出合并的最大总得分。
示例:石子数量为 [3, 4, 6, 5] 排成环形。一种可能的合并顺序是:
- 合并 (3, 4) 得 7 分,石子变为 [7, 6, 5]
- 合并 (5, 7) 得 12 分,石子变为 [12, 6](注意环形相邻,5 和 7 相邻)
- 合并 (6, 12) 得 18 分,总得分为 7+12+18=37 分。但可能存在更大得分的合并方式。
解题过程:
-
问题分析
环形结构增加了相邻关系的复杂性。一个常用技巧是将环形问题转化为线性问题:将原数组复制一份接到后面,形成长度为 2N 的数组。这样,原环形中任意一种合并顺序,都可以对应到这个长度为 2N 的数组中某个长度为 N 的连续子数组的合并问题。 -
状态定义
设 dp[i][j] 表示合并从第 i 堆到第 j 堆(i 和 j 是复制后数组的索引,且 i <= j)的所有石子成一堆所能获得的最大得分。注意,这里 i 和 j 是复制后数组的索引,取值范围是 0 到 2N-1。 -
状态转移方程
考虑最后一次合并,它一定是将两堆合并成一堆。假设最后一次合并时,左边那堆是由 i 到 k 合并而成的,右边那堆是由 k+1 到 j 合并而成的。那么合并 i 到 j 的得分为:dp[i][k] + dp[k+1][j] + sum(i, j),其中 sum(i, j) 是 i 到 j 的石子总数(因为最后一步将两堆合并,新堆石子数为这两堆之和,得分即为这个和)。
由于我们要求最大得分,需要枚举所有可能的分割点 k:
dp[i][j] = max(dp[i][k] + dp[k+1][j] + sum(i, j)),其中 k 从 i 到 j-1。
注意,当 i == j 时,只有一堆石子,不需要合并,得分为 0。 -
前缀和优化
为了快速计算 sum(i, j),我们可以使用前缀和数组 preSum,其中 preSum[0]=0, preSum[t]=a[0]+a[1]+...+a[t-1](复制后的数组)。那么 sum(i, j) = preSum[j+1] - preSum[i]。 -
环形处理
我们只需在复制后的数组上,对每个可能的起点 i(0 <= i < N),计算长度为 N 的区间 [i, i+N-1] 的最大得分 dp[i][i+N-1]。最终答案就是所有这样的 dp[i][i+N-1] 中的最大值。 -
计算顺序
由于 dp[i][j] 依赖于更短的区间(即区间长度更小),我们需要按区间长度从小到大计算。先计算所有长度为 1 的区间(得分均为 0),然后长度从 2 到 N 进行计算。 -
举例演算
以示例 N=4, a=[3,4,6,5] 为例。复制后数组为 [3,4,6,5,3,4,6,5]。
计算前缀和 preSum=[0,3,7,13,18,21,25,31,36]。
计算 dp[0][1]:k 只能为 0,dp[0][1] = dp[0][0]+dp[1][1]+sum(0,1) = 0+0+(7-0)=7。
类似计算其他长度 2 的区间。
然后计算长度 3 的区间,例如 dp[0][2]:- k=0: dp[0][0]+dp[1][2]+sum(0,2) = 0+dp[1][2]+(13-0)
dp[1][2] 需要提前算好:k=1 时,dp[1][2]=dp[1][1]+dp[2][2]+sum(1,2)=0+0+(13-3)=10
所以 k=0 时值为 0+10+13=23 - k=1: dp[0][1]+dp[2][2]+sum(0,2) = 7+0+13=20
取最大值 23,所以 dp[0][2]=23。
继续计算所有区间,最后对于每个起点 i,计算 dp[i][i+3](长度 4),取最大值。
- k=0: dp[0][0]+dp[1][2]+sum(0,2) = 0+dp[1][2]+(13-0)
-
最终答案
最大得分 = max(dp[i][i+N-1]),其中 i 从 0 到 N-1。
这个解法的时间复杂度为 O(N^3)(因为有三重循环:区间长度、起点、分割点),空间复杂度为 O(N^2)。通过环形转线性的技巧,将环形问题转化为线性区间 DP 问题,从而可以求解。