环形石子合并的最小得分问题
字数 1070 2025-10-31 22:46:15

环形石子合并的最小得分问题

题目描述:
有n堆石子排成一个环形,每堆石子的数量用数组stones表示,其中stones[i]表示第i堆石子的数量。每次操作可以将相邻的两堆石子合并为一堆,合并的代价为这两堆石子的数量之和。请找出将所有石子合并成一堆的最小总代价。

解题过程:

  1. 问题分析:
  • 石子排成环形,意味着第一堆和最后一堆石子也是相邻的
  • 每次合并相邻的两堆石子,合并代价为两堆石子数量之和
  • 目标是找到合并顺序使得总代价最小
  1. 环形转线性:
    由于是环形结构,我们可以将其转化为线性问题。常用的方法是复制数组:
  • 将原数组stones复制一份接在后面,得到长度为2n的新数组
  • 在新数组上考虑所有长度为n的连续子数组,每个子数组对应环形的一种展开方式
  1. 动态规划定义:
    定义dp[i][j]表示合并第i堆到第j堆石子的最小代价(i ≤ j)

  2. 状态转移方程:

  • 当i = j时,只有一堆石子,不需要合并,dp[i][j] = 0
  • 当i < j时,我们需要考虑最后一次合并的位置k(i ≤ k < j)
  • 最后一次合并的代价是i到j所有石子的总和
  • 状态转移方程:dp[i][j] = min(dp[i][k] + dp[k+1][j] + sum(i,j)),其中k从i到j-1
  1. 前缀和优化:
    为了快速计算区间和sum(i,j),我们可以预处理前缀和数组prefix:
  • prefix[0] = 0
  • prefix[i] = stones[0] + stones[1] + ... + stones[i-1]
  • sum(i,j) = prefix[j+1] - prefix[i]
  1. 计算顺序:
    由于dp[i][j]依赖于更短的区间,我们需要按区间长度从小到大计算:
  • 先计算长度为2的区间,然后长度为3,直到长度为n
  1. 环形处理:
    对于环形问题,我们在长度为2n的数组上计算,然后取所有长度为n的区间的最小值作为答案

  2. 算法步骤:
    步骤1:如果n=1,直接返回0
    步骤2:创建长度为2n的扩展数组
    步骤3:计算前缀和数组
    步骤4:初始化dp数组,对角线元素为0
    步骤5:按区间长度len从2到n遍历
    步骤6:对于每个起始位置i,计算结束位置j = i + len - 1
    步骤7:遍历所有可能的分割点k,计算最小代价
    步骤8:在所有长度为n的区间中找最小值

  3. 时间复杂度:O(n³),空间复杂度:O(n²)

这个算法通过环形转线性的技巧,将复杂的环形问题转化为经典的区间动态规划问题,是处理环形结构问题的典型方法。

环形石子合并的最小得分问题 题目描述: 有n堆石子排成一个环形,每堆石子的数量用数组stones表示,其中stones[ i ]表示第i堆石子的数量。每次操作可以将相邻的两堆石子合并为一堆,合并的代价为这两堆石子的数量之和。请找出将所有石子合并成一堆的最小总代价。 解题过程: 问题分析: 石子排成环形,意味着第一堆和最后一堆石子也是相邻的 每次合并相邻的两堆石子,合并代价为两堆石子数量之和 目标是找到合并顺序使得总代价最小 环形转线性: 由于是环形结构,我们可以将其转化为线性问题。常用的方法是复制数组: 将原数组stones复制一份接在后面,得到长度为2n的新数组 在新数组上考虑所有长度为n的连续子数组,每个子数组对应环形的一种展开方式 动态规划定义: 定义dp[ i][ j ]表示合并第i堆到第j堆石子的最小代价(i ≤ j) 状态转移方程: 当i = j时,只有一堆石子,不需要合并,dp[ i][ j ] = 0 当i < j时,我们需要考虑最后一次合并的位置k(i ≤ k < j) 最后一次合并的代价是i到j所有石子的总和 状态转移方程:dp[ i][ j] = min(dp[ i][ k] + dp[ k+1][ j ] + sum(i,j)),其中k从i到j-1 前缀和优化: 为了快速计算区间和sum(i,j),我们可以预处理前缀和数组prefix: prefix[ 0 ] = 0 prefix[ i] = stones[ 0] + stones[ 1] + ... + stones[ i-1 ] sum(i,j) = prefix[ j+1] - prefix[ i ] 计算顺序: 由于dp[ i][ j ]依赖于更短的区间,我们需要按区间长度从小到大计算: 先计算长度为2的区间,然后长度为3,直到长度为n 环形处理: 对于环形问题,我们在长度为2n的数组上计算,然后取所有长度为n的区间的最小值作为答案 算法步骤: 步骤1:如果n=1,直接返回0 步骤2:创建长度为2n的扩展数组 步骤3:计算前缀和数组 步骤4:初始化dp数组,对角线元素为0 步骤5:按区间长度len从2到n遍历 步骤6:对于每个起始位置i,计算结束位置j = i + len - 1 步骤7:遍历所有可能的分割点k,计算最小代价 步骤8:在所有长度为n的区间中找最小值 时间复杂度:O(n³),空间复杂度:O(n²) 这个算法通过环形转线性的技巧,将复杂的环形问题转化为经典的区间动态规划问题,是处理环形结构问题的典型方法。