带限制的矩阵链乘最小乘法次数问题(矩阵维度带约束版本)
字数 5668 2025-12-06 01:32:28

带限制的矩阵链乘最小乘法次数问题(矩阵维度带约束版本)

题目描述
给定一系列矩阵 \(A_1, A_2, \dots, A_n\),其中矩阵 \(A_i\) 的维度为 \(p_{i-1} \times p_i\)。矩阵相乘的次数取决于乘法的顺序。标准矩阵链乘问题的目标是找到一种完全括号化方案,使得计算矩阵乘积 \(A_1 A_2 \dots A_n\) 所需标量乘法次数最少。
在本问题中,额外增加一个约束:某些相邻矩阵对不能直接相乘(即不能以相邻顺序进行乘法),这个约束由布尔矩阵 \(C\) 表示,其中 \(C[i][j] = 0\) 表示矩阵 \(A_i, A_{i+1}, \dots, A_j\) 不能作为一个连续子链相乘(即不能将这段矩阵视为一个连续的块进行括号化)。
求满足约束的最少乘法次数。如果不存在可行的括号化方式,返回 -1。


解题过程

这是一个区间动态规划问题。基本框架是标准的矩阵链乘 DP,但需要额外处理约束条件。

1. 状态定义
\(dp[i][j]\) 表示计算矩阵子链 \(A_i A_{i+1} \dots A_j\) 所需的最小标量乘法次数。若子链不可行(受约束或无解),则 \(dp[i][j] = \infty\)
最终答案:\(dp[1][n]\)(若为无穷大则返回 -1)。

2. 约束条件
约束 \(C[i][j] = 0\) 表示:不能将 \(A_i \dots A_j\) 视为一个连续的块(即不能在这个区间内不插入括号,作为一个整体相乘)。注意:即使 \(C[i][j] = 0\),仍然可以通过在区间内划分,使得左右两部分各自计算后再乘起来,只要划分点 \(k\) 满足两段分别可行。

3. 状态转移
考虑区间 \([i, j]\)

  • 如果 \(i = j\),只有一个矩阵,无需乘法,\(dp[i][j] = 0\)

  • 如果 \(i < j\),我们需要找一个划分点 \(k\)\(i \le k < j\)),将链分成 \(A_i \dots A_k\)\(A_{k+1} \dots A_j\) 两部分。
    乘法次数 = 左部分乘法次数 + 右部分乘法次数 + 合并两部分的乘法次数。
    合并乘法次数 = \(p_{i-1} \times p_k \times p_j\)

  • 但这里有一个限制:如果划分点 \(k = i\) 且右部分长度为 1?不,我们需要考虑约束条件。
    实际上,约束是:当我们在某个划分点 \(k\) 将区间分成两段时,整个区间作为一个整体是否被允许?如果 \(C[i][j] = 0\),这意味着我们不能将整个区间视为一个“不括号化”的块,但在区间 DP 中,我们总是会划分,所以约束影响的是:\(C[i][j] = 1\) 时,我们可以将区间视为整体,不进行任何划分(即区间内不插入括号)吗? 不,在标准矩阵链乘中,我们总可以划分或不划分,但这里约束是对整个区间作为一个整体相乘的限制。
    更准确的理解是:如果我们想将 \(A_i \dots A_j\) 作为一个整体(不进一步括号化)来计算,那么必须 \(C[i][j] = 1\),否则不能这样。但 DP 中我们总是划分成两段,所以这个约束实际上影响的是是否允许在区间内部不划分。然而,区间 DP 中即使允许整体不划分,也需要比较划分与不划分的代价。但矩阵链乘中,不划分意味着区间内只有一个矩阵(即 i=j),否则不划分是不允许的,因为乘法是二元运算,必须两两结合。

    所以正确的理解是:约束 \(C[i][j] = 0\) 表示“不能将 \(A_i \dots A_j\) 作为一个连续块相乘”意味着:我们不能在计算过程中将 \(A_i \dots A_j\) 看作一个整体与其它矩阵相乘。换句话说,在递归计算时,如果 \(C[i][j] = 0\),则区间 \([i, j]\) 必须被进一步划分,不能直接作为一个整体返回。但 DP 中我们本来就会划分,所以只需要在合并时注意,当我们要将左右两个子区间合并时,左子区间必须与右子区间相邻,且它们各自是可行的。但约束 \(C[i][j]\) 针对整个区间,所以其实它影响的是:当我们将区间分为两段时,左段和右段各自独立计算,合并时就是两矩阵相乘,不需要整体区间满足 \(C[i][j] = 1\)

    那么约束怎么用?仔细看:如果 \(C[i][j] = 0\),意味着我们不能将 \(A_i \dots A_j\) 作为一个整体与外部矩阵相乘。但是在计算 \(dp[i][j]\) 时,我们不需要 \(C[i][j] = 1\),因为 \(dp[i][j]\) 只是计算这个子链的最小代价,不涉及外部。所以约束在递归计算中并无影响?不对,原题意思是:某些相邻矩阵对不能直接相乘,扩展为“某些连续子链不能作为一个整体相乘”。那么,在 DP 中,当我们尝试将区间分成两段时,两段各自必须是一个“合法的可相乘的子链”,即 \(C\) 为 1 或者进一步划分。

    我们重新定义约束:\(C[i][j] = 1\) 表示子链 \(A_i \dots A_j\) 可以作为一个整体相乘(即可以不加括号直接按顺序乘),否则必须划分。在 DP 中,整体相乘对应不划分,代价是 \(p_{i-1} \times p_{j-1} \times p_j\) 吗?不对,整体相乘不是一次乘法,而是顺序乘,其代价是固定顺序乘的代价。但固定顺序乘的代价不一定最小。实际上,矩阵链乘中,如果不加括号,就是顺序乘,代价是固定的,但我们可以加括号改变顺序。
    所以正确的建模是:
    对于区间 [i, j],计算它的最小乘法次数,有两种情况:

    1. 不加括号,直接按顺序乘,这要求 \(C[i][j] = 1\)
    2. 在某个 k 处划分,左右分别加括号,这总是允许的,只要左右子链可行。

    这样转移方程为:

    • 先初始化 \(dp[i][j] = \infty\)
    • 如果 \(C[i][j] = 1\),则可以直接顺序乘,代价是 \(\sum_{t=i}^{j-1} p_{i-1} \times p_t \times p_j\)?不对,顺序乘的代价是固定的,假设我们按 \(((A_i A_{i+1}) A_{i+2}) \dots\) 顺序,这是最左顺序,乘法次数 = \(p_{i-1} p_i p_j + p_{i-1} p_{i+1} p_j + \dots + p_{i-1} p_{j-1} p_j\)。但这不是最小代价,只是为了满足不括号化的代价。
      实际上,如果 \(C[i][j] = 1\),意味着我们可以不划分,此时计算这个区间的代价就是按给定顺序乘的代价,但“不划分”不代表顺序固定,只是说可以作为一个块直接乘,但内部的乘法顺序可以任意吗?不,如果不划分,那就是默认顺序乘,代价固定。如果我们想得到最小代价,那还是要括号化,除非约束禁止括号化。但约束只是说“可以作为一个整体相乘”,并不禁止括号化。
      所以这里有点绕。我们简化:约束 \(C[i][j] = 1\) 表示“允许将 i..j 视为一个整体”,在计算时,我们可以选择不划分(即直接按顺序乘),也可以选择划分。如果不划分,代价是固定顺序乘的代价;如果划分,代价是 DP 子问题代价之和。我们取最小。

    但这样复杂度高,因为要算固定顺序乘的代价。但原题可能意图是:约束只影响是否允许作为一个整体,不影响内部是否括号化。我们采用更简单的理解:约束只影响整个区间是否允许作为一个块,而不影响内部划分。 在 DP 中,我们总是划分,所以约束在最后合并时检查:当我们计算 \(dp[i][j]\) 时,如果 \(C[i][j] = 0\),则这个区间不能作为一个整体输出,但 \(dp[i][j]\) 只是中间结果,可以继续用于更大的区间,所以应该允许。
    但原题说“某些相邻矩阵对不能直接相乘”,这意味着如果 \(C[i][i+1] = 0\),则 \(A_i\)\(A_{i+1}\) 不能直接乘,但可以通过括号化让它们不直接乘。比如 A1, A2, A3,如果 C[1][2]=0,我们可以先算 A2*A3,再与 A1 乘。所以 C 只是限制相邻乘,不是限制区间。

    因此,我们采用更常见的理解:约束 \(C[i][j] = 0\) 表示子链 i..j 不能直接作为一个块相乘。在 DP 中,当我们考虑区间 [i, j] 时,如果 C[i][j] = 1,则我们可以用整体相乘的代价来更新 dp[i][j];否则只能用划分。但整体相乘的代价怎么算?就是顺序乘,乘法次数是 \(p_{i-1} p_i p_{i+1} + p_{i-1} p_{i+1} p_{i+2} + \dots\) 吗?这不就是固定顺序的代价。但这样还不如直接划分。所以可能约束的意思是:C[i][j]=1 表示子链 i..j 可以相乘(不违反约束),否则不能相乘,即 dp[i][j] 必须为 INF。

    我们采用这个简单理解:C[i][j]=1 表示允许子链 i..j 作为一个可计算的块,否则不允许。在计算 dp[i][j] 时,只有 C[i][j]=1 时,我们才计算它,否则 dp[i][j]=INF。但这样整个链必须 C[1][n]=1 才可能有解。这似乎太强。

    仔细看原题描述:某些相邻矩阵对不能直接相乘。这可以扩展为:如果 C[i][j]=0,则不能将 i..j 作为一个整体相乘,但内部划分后可以。在 DP 中,整体相乘对应不划分,但我们可以划分,所以 C[i][j]=0 只是禁止不划分的情况,不禁止划分。

    所以转移方程修正:

    • 如果区间长度=1,dp[i][i] = 0,不需要 C[i][i]=1,因为单个矩阵总是可乘。
    • 如果长度>1,考虑划分点 k,分 [i, k] 和 [k+1, j] 两段,分别计算代价,再加上合并代价。这总是允许的,只要左右两段可行。
    • 另外,如果 C[i][j]=1,我们还可以考虑“不划分”,即整体顺序乘的代价,但顺序乘的代价不一定最小,所以我们可以忽略这种情况,因为划分总能达到更小或相等代价(因为矩阵链乘不加括号的代价通常大于最优括号化的代价)。但为了完整性,我们可以算一下整体顺序乘的代价:设整体顺序乘,就是从左到右依次乘,乘法次数 = sum_{t=i}^{j-1} p_{i-1} * p_t * p_j。这可以在 O(n) 时间算出。然后与划分的代价取 min。

    所以转移方程为:
    dp[i][j] = min(
    min_{k=i}^{j-1} (dp[i][k] + dp[k+1][j] + p_{i-1} * p_k * p_j), // 划分
    (如果 C[i][j]=1) 则顺序乘代价
    )

    顺序乘代价 = 0 如果 i=j,否则 = sum_{t=i}^{j-1} p_{i-1} * p_t * p_j。

4. 计算顺序
区间长度 len 从 2 到 n 递增计算。

5. 初始化
dp[i][i] = 0,对任意 i。

6. 最终答案
dp[1][n] 如果为无穷大则返回 -1,否则返回该值。


示例解释

假设 n=3,p = [10, 20, 30, 40],即 A1:10x20, A2:20x30, A3:30x40。
约束 C[1][2]=0(A1 和 A2 不能直接乘),C[2][3]=1,C[1][3]=1。
计算:

  • dp[1][1]=0, dp[2][2]=0, dp[3][3]=0。
  • len=2:
    [1,2]: C[1][2]=0,不能整体顺序乘,只能划分。但划分只有 k=1,分 [1,1] 和 [2,2],代价 = 0+0+102030=6000,所以 dp[1][2]=6000。
    [2,3]: C[2][3]=1,划分代价 k=2: 0+0+203040=24000,整体顺序乘代价 = 203040=24000,取 min=24000。dp[2][3]=24000。
  • len=3: [1,3]
    划分点 k=1: dp[1][1]+dp[2][3]+102040=0+24000+8000=32000。
    划分点 k=2: dp[1][2]+dp[3][3]+103040=6000+0+12000=18000。
    整体顺序乘(C[1][3]=1):代价=102040+103040=8000+12000=20000。
    取最小=18000。
    所以最小乘法次数=18000。

复杂度
时间复杂度 O(n^3),空间复杂度 O(n^2)。


核心点

  • 约束 C 只影响“整体顺序乘”是否允许,不影响划分。
  • 状态转移时,比较划分与整体顺序乘的代价,取最小。
  • 若无可行方案(所有 dp[1][n] 为无穷大)则返回 -1。
带限制的矩阵链乘最小乘法次数问题(矩阵维度带约束版本) 题目描述 给定一系列矩阵 \( A_ 1, A_ 2, \dots, A_ n \),其中矩阵 \( A_ i \) 的维度为 \( p_ {i-1} \times p_ i \)。矩阵相乘的次数取决于乘法的顺序。标准矩阵链乘问题的目标是找到一种完全括号化方案,使得计算矩阵乘积 \( A_ 1 A_ 2 \dots A_ n \) 所需标量乘法次数最少。 在本问题中, 额外增加一个约束 :某些相邻矩阵对不能直接相乘(即不能以相邻顺序进行乘法),这个约束由布尔矩阵 \( C \) 表示,其中 \( C[ i][ j] = 0 \) 表示矩阵 \( A_ i, A_ {i+1}, \dots, A_ j \) 不能作为一个连续子链相乘(即不能将这段矩阵视为一个连续的块进行括号化)。 求满足约束的最少乘法次数。如果不存在可行的括号化方式,返回 -1。 解题过程 这是一个区间动态规划问题。基本框架是标准的矩阵链乘 DP,但需要额外处理约束条件。 1. 状态定义 设 \( dp[ i][ j] \) 表示计算矩阵子链 \( A_ i A_ {i+1} \dots A_ j \) 所需的最小标量乘法次数。若子链不可行(受约束或无解),则 \( dp[ i][ j ] = \infty \)。 最终答案:\( dp[ 1][ n ] \)(若为无穷大则返回 -1)。 2. 约束条件 约束 \( C[ i][ j] = 0 \) 表示:不能将 \( A_ i \dots A_ j \) 视为一个连续的块(即不能在这个区间内不插入括号,作为一个整体相乘)。注意:即使 \( C[ i][ j ] = 0 \),仍然可以通过在区间内划分,使得左右两部分各自计算后再乘起来,只要划分点 \( k \) 满足两段分别可行。 3. 状态转移 考虑区间 \( [ i, j ] \): 如果 \( i = j \),只有一个矩阵,无需乘法,\( dp[ i][ j ] = 0 \)。 如果 \( i < j \),我们需要找一个划分点 \( k \)(\( i \le k < j \)),将链分成 \( A_ i \dots A_ k \) 和 \( A_ {k+1} \dots A_ j \) 两部分。 乘法次数 = 左部分乘法次数 + 右部分乘法次数 + 合并两部分的乘法次数。 合并乘法次数 = \( p_ {i-1} \times p_ k \times p_ j \)。 但这里有一个限制:如果划分点 \( k = i \) 且右部分长度为 1?不,我们需要考虑约束条件。 实际上,约束是:当我们在某个划分点 \( k \) 将区间分成两段时, 整个区间 作为一个整体是否被允许?如果 \( C[ i][ j] = 0 \),这意味着我们不能将整个区间视为一个“不括号化”的块,但在区间 DP 中,我们总是会划分,所以约束影响的是: 当 \( C[ i][ j] = 1 \) 时,我们可以将区间视为整体,不进行任何划分(即区间内不插入括号)吗? 不,在标准矩阵链乘中,我们总可以划分或不划分,但这里约束是对整个区间作为一个整体相乘的限制。 更准确的理解是:如果我们想将 \( A_ i \dots A_ j \) 作为一个整体(不进一步括号化)来计算,那么必须 \( C[ i][ j] = 1 \),否则不能这样。但 DP 中我们总是划分成两段,所以这个约束实际上影响的是 是否允许在区间内部不划分 。然而,区间 DP 中即使允许整体不划分,也需要比较划分与不划分的代价。但矩阵链乘中,不划分意味着区间内只有一个矩阵(即 i=j),否则不划分是不允许的,因为乘法是二元运算,必须两两结合。 所以正确的理解是:约束 \( C[ i][ j] = 0 \) 表示“不能将 \( A_ i \dots A_ j \) 作为一个连续块相乘”意味着:我们不能在计算过程中将 \( A_ i \dots A_ j \) 看作一个整体与其它矩阵相乘。换句话说,在递归计算时,如果 \( C[ i][ j] = 0 \),则区间 \( [ i, j] \) 必须被进一步划分,不能直接作为一个整体返回。但 DP 中我们本来就会划分,所以只需要在合并时注意, 当我们要将左右两个子区间合并时,左子区间必须与右子区间相邻,且它们各自是可行的 。但约束 \( C[ i][ j] \) 针对整个区间,所以其实它影响的是:当我们将区间分为两段时,左段和右段各自独立计算,合并时就是两矩阵相乘,不需要整体区间满足 \( C[ i][ j ] = 1 \)。 那么约束怎么用?仔细看:如果 \( C[ i][ j] = 0 \),意味着我们不能将 \( A_ i \dots A_ j \) 作为一个整体与外部矩阵相乘。但是在计算 \( dp[ i][ j] \) 时,我们不需要 \( C[ i][ j] = 1 \),因为 \( dp[ i][ j ] \) 只是计算这个子链的最小代价,不涉及外部。所以约束在递归计算中并无影响?不对,原题意思是:某些相邻矩阵对不能直接相乘,扩展为“某些连续子链不能作为一个整体相乘”。那么,在 DP 中,当我们尝试将区间分成两段时,两段各自必须是一个“合法的可相乘的子链”,即 \( C \) 为 1 或者进一步划分。 我们重新定义约束:\( C[ i][ j] = 1 \) 表示子链 \( A_ i \dots A_ j \) 可以作为一个整体相乘(即可以不加括号直接按顺序乘),否则必须划分。在 DP 中,整体相乘对应不划分,代价是 \( p_ {i-1} \times p_ {j-1} \times p_ j \) 吗?不对,整体相乘不是一次乘法,而是顺序乘,其代价是固定顺序乘的代价。但固定顺序乘的代价不一定最小。实际上,矩阵链乘中,如果不加括号,就是顺序乘,代价是固定的,但我们可以加括号改变顺序。 所以正确的建模是: 对于区间 [ i, j ],计算它的最小乘法次数,有两种情况: 不加括号,直接按顺序乘,这要求 \( C[ i][ j ] = 1 \)。 在某个 k 处划分,左右分别加括号,这总是允许的,只要左右子链可行。 这样转移方程为: 先初始化 \( dp[ i][ j ] = \infty \)。 如果 \( C[ i][ j] = 1 \),则可以直接顺序乘,代价是 \( \sum_ {t=i}^{j-1} p_ {i-1} \times p_ t \times p_ j \)?不对,顺序乘的代价是固定的,假设我们按 \( ((A_ i A_ {i+1}) A_ {i+2}) \dots \) 顺序,这是最左顺序,乘法次数 = \( p_ {i-1} p_ i p_ j + p_ {i-1} p_ {i+1} p_ j + \dots + p_ {i-1} p_ {j-1} p_ j \)。但这不是最小代价,只是为了满足不括号化的代价。 实际上,如果 \( C[ i][ j ] = 1 \),意味着我们可以不划分,此时计算这个区间的代价就是按给定顺序乘的代价,但“不划分”不代表顺序固定,只是说可以作为一个块直接乘,但内部的乘法顺序可以任意吗?不,如果不划分,那就是默认顺序乘,代价固定。如果我们想得到最小代价,那还是要括号化,除非约束禁止括号化。但约束只是说“可以作为一个整体相乘”,并不禁止括号化。 所以这里有点绕。我们简化:约束 \( C[ i][ j ] = 1 \) 表示“允许将 i..j 视为一个整体”,在计算时,我们可以选择不划分(即直接按顺序乘),也可以选择划分。如果不划分,代价是固定顺序乘的代价;如果划分,代价是 DP 子问题代价之和。我们取最小。 但这样复杂度高,因为要算固定顺序乘的代价。但原题可能意图是:约束只影响是否允许作为一个整体,不影响内部是否括号化。我们采用更简单的理解: 约束只影响整个区间是否允许作为一个块,而不影响内部划分。 在 DP 中,我们总是划分,所以约束在最后合并时检查:当我们计算 \( dp[ i][ j] \) 时,如果 \( C[ i][ j] = 0 \),则这个区间不能作为一个整体输出,但 \( dp[ i][ j ] \) 只是中间结果,可以继续用于更大的区间,所以应该允许。 但原题说“某些相邻矩阵对不能直接相乘”,这意味着如果 \( C[ i][ i+1] = 0 \),则 \( A_ i \) 和 \( A_ {i+1} \) 不能直接乘,但可以通过括号化让它们不直接乘。比如 A1, A2, A3,如果 C[ 1][ 2]=0,我们可以先算 A2* A3,再与 A1 乘。所以 C 只是限制相邻乘,不是限制区间。 因此,我们采用更常见的理解:约束 \( C[ i][ j] = 0 \) 表示子链 i..j 不能直接作为一个块相乘。在 DP 中,当我们考虑区间 [ i, j] 时,如果 C[ i][ j] = 1,则我们可以用整体相乘的代价来更新 dp[ i][ j];否则只能用划分。但整体相乘的代价怎么算?就是顺序乘,乘法次数是 \( p_ {i-1} p_ i p_ {i+1} + p_ {i-1} p_ {i+1} p_ {i+2} + \dots \) 吗?这不就是固定顺序的代价。但这样还不如直接划分。所以可能约束的意思是:C[ i][ j]=1 表示子链 i..j 可以相乘(不违反约束),否则不能相乘,即 dp[ i][ j ] 必须为 INF。 我们采用这个简单理解:C[ i][ j]=1 表示允许子链 i..j 作为一个可计算的块,否则不允许。在计算 dp[ i][ j] 时,只有 C[ i][ j]=1 时,我们才计算它,否则 dp[ i][ j]=INF。但这样整个链必须 C[ 1][ n ]=1 才可能有解。这似乎太强。 仔细看原题描述:某些相邻矩阵对不能直接相乘。这可以扩展为:如果 C[ i][ j]=0,则不能将 i..j 作为一个整体相乘,但内部划分后可以。在 DP 中,整体相乘对应不划分,但我们可以划分,所以 C[ i][ j ]=0 只是禁止不划分的情况,不禁止划分。 所以转移方程修正: 如果区间长度=1,dp[ i][ i] = 0,不需要 C[ i][ i ]=1,因为单个矩阵总是可乘。 如果长度>1,考虑划分点 k,分 [ i, k] 和 [ k+1, j ] 两段,分别计算代价,再加上合并代价。这总是允许的,只要左右两段可行。 另外,如果 C[ i][ j]=1,我们还可以考虑“不划分”,即整体顺序乘的代价,但顺序乘的代价不一定最小,所以我们可以忽略这种情况,因为划分总能达到更小或相等代价(因为矩阵链乘不加括号的代价通常大于最优括号化的代价)。但为了完整性,我们可以算一下整体顺序乘的代价:设整体顺序乘,就是从左到右依次乘,乘法次数 = sum_ {t=i}^{j-1} p_ {i-1} * p_ t * p_ j。这可以在 O(n) 时间算出。然后与划分的代价取 min。 所以转移方程为: dp[ i][ j ] = min( min_ {k=i}^{j-1} (dp[ i][ k] + dp[ k+1][ j] + p_ {i-1} * p_ k * p_ j), // 划分 (如果 C[ i][ j ]=1) 则顺序乘代价 ) 顺序乘代价 = 0 如果 i=j,否则 = sum_ {t=i}^{j-1} p_ {i-1} * p_ t * p_ j。 4. 计算顺序 区间长度 len 从 2 到 n 递增计算。 5. 初始化 dp[ i][ i ] = 0,对任意 i。 6. 最终答案 dp[ 1][ n ] 如果为无穷大则返回 -1,否则返回该值。 示例解释 假设 n=3,p = [ 10, 20, 30, 40 ],即 A1:10x20, A2:20x30, A3:30x40。 约束 C[ 1][ 2]=0(A1 和 A2 不能直接乘),C[ 2][ 3]=1,C[ 1][ 3 ]=1。 计算: dp[ 1][ 1]=0, dp[ 2][ 2]=0, dp[ 3][ 3 ]=0。 len=2: [ 1,2]: C[ 1][ 2]=0,不能整体顺序乘,只能划分。但划分只有 k=1,分 [ 1,1] 和 [ 2,2],代价 = 0+0+10 20 30=6000,所以 dp[ 1][ 2 ]=6000。 [ 2,3]: C[ 2][ 3]=1,划分代价 k=2: 0+0+20 30 40=24000,整体顺序乘代价 = 20 30 40=24000,取 min=24000。dp[ 2][ 3 ]=24000。 len=3: [ 1,3 ] 划分点 k=1: dp[ 1][ 1]+dp[ 2][ 3]+10 20 40=0+24000+8000=32000。 划分点 k=2: dp[ 1][ 2]+dp[ 3][ 3]+10 30 40=6000+0+12000=18000。 整体顺序乘(C[ 1][ 3]=1):代价=10 20 40+10 30 40=8000+12000=20000。 取最小=18000。 所以最小乘法次数=18000。 复杂度 时间复杂度 O(n^3),空间复杂度 O(n^2)。 核心点 约束 C 只影响“整体顺序乘”是否允许,不影响划分。 状态转移时,比较划分与整体顺序乘的代价,取最小。 若无可行方案(所有 dp[ 1][ n ] 为无穷大)则返回 -1。