环形石子合并(最大得分)问题
字数 1885 2025-12-05 19:46:02

环形石子合并(最大得分)问题

题目描述:有 N 堆石子排成一个环形,第 i 堆石子有 a[i] 个。现在要将这 N 堆石子合并成一堆,合并的规则是每次只能合并相邻的两堆石子,合并的得分是新一堆石子的总数。目标是求出合并的最大总得分。

示例:石子数量为 [3, 4, 6, 5] 排成环形。一种可能的合并顺序是:

  1. 合并 (3, 4) 得 7 分,石子变为 [7, 6, 5]
  2. 合并 (5, 7) 得 12 分,石子变为 [12, 6](注意环形相邻,5 和 7 相邻)
  3. 合并 (6, 12) 得 18 分,总得分为 7+12+18=37 分。但可能存在更大得分的合并方式。

解题过程:

  1. 问题分析
    环形结构增加了相邻关系的复杂性。一个常用技巧是将环形问题转化为线性问题:将原数组复制一份接到后面,形成长度为 2N 的数组。这样,原环形中任意一种合并顺序,都可以对应到这个长度为 2N 的数组中某个长度为 N 的连续子数组的合并问题。

  2. 状态定义
    设 dp[i][j] 表示合并从第 i 堆到第 j 堆(i 和 j 是复制后数组的索引,且 i <= j)的所有石子成一堆所能获得的最大得分。注意,这里 i 和 j 是复制后数组的索引,取值范围是 0 到 2N-1。

  3. 状态转移方程
    考虑最后一次合并,它一定是将两堆合并成一堆。假设最后一次合并时,左边那堆是由 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。

  4. 前缀和优化
    为了快速计算 sum(i, j),我们可以使用前缀和数组 preSum,其中 preSum[0]=0, preSum[t]=a[0]+a[1]+...+a[t-1](复制后的数组)。那么 sum(i, j) = preSum[j+1] - preSum[i]。

  5. 环形处理
    我们只需在复制后的数组上,对每个可能的起点 i(0 <= i < N),计算长度为 N 的区间 [i, i+N-1] 的最大得分 dp[i][i+N-1]。最终答案就是所有这样的 dp[i][i+N-1] 中的最大值。

  6. 计算顺序
    由于 dp[i][j] 依赖于更短的区间(即区间长度更小),我们需要按区间长度从小到大计算。先计算所有长度为 1 的区间(得分均为 0),然后长度从 2 到 N 进行计算。

  7. 举例演算
    以示例 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),取最大值。
  8. 最终答案
    最大得分 = max(dp[i][i+N-1]),其中 i 从 0 到 N-1。

这个解法的时间复杂度为 O(N^3)(因为有三重循环:区间长度、起点、分割点),空间复杂度为 O(N^2)。通过环形转线性的技巧,将环形问题转化为线性区间 DP 问题,从而可以求解。

环形石子合并(最大得分)问题 题目描述:有 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),取最大值。 最终答案 最大得分 = max(dp[ i][ i+N-1 ]),其中 i 从 0 到 N-1。 这个解法的时间复杂度为 O(N^3)(因为有三重循环:区间长度、起点、分割点),空间复杂度为 O(N^2)。通过环形转线性的技巧,将环形问题转化为线性区间 DP 问题,从而可以求解。