本文最后更新于 2025年10月23日 晚上
                  
                
              
            
            
              
                
                问题描述 
设有一个长度为L L L n n n ( p 1 , p 2 , … , p n ) (p_1,p_2,\dots,p_n) ( p 1  , p 2  , … , p n  ) n + 1 n+1 n + 1 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include  <iostream>  #include  <string>  #include  <cmath>  #include  <vector>  #include  <algorithm>  using  namespace  std;void  MinCost (int  L,int  n,int  *p) int  main ()  int  L, n;int  *p;new  int [n+2 ];0 ] = 0 ;+1 ] = L;for (int  i=1 ;i<n+1 ;i++){MinCost (L,n,p);return  0 ;
样例输入:
样例输出:
问题分析 
定义子问题: p [ i ] p[i] p [ i ] p [ j ] p[j] p [ j ] p [ i ] p[i] p [ i ] p [ j ] p[j] p [ j ] 
 
切割点的选择: p [ i ] p[i] p [ i ] p [ j ] p[j] p [ j ] k k k p [ k ] p[k] p [ k ] i < k < j i < k < j i < k < j 
左半部分:从 p [ i ] p[i] p [ i ] p [ k ] p[k] p [ k ] d p [ i ] [ k ] dp[i][k] d p [ i ] [ k ]  
右半部分:从 p [ k ] p[k] p [ k ] p [ j ] p[j] p [ j ] d p [ k ] [ j ] dp[k][j] d p [ k ] [ j ]  
 
此时,整个区间的成本包括切割点 k k k p [ j ] − p [ i ] p[j] - p[i] p [ j ] − p [ i ] 
 
状态转移方程: 
 
 
d p [ i ] [ j ] = min  i < k < j ( d p [ i ] [ k ] + d p [ k ] [ j ] + ( p [ j ] − p [ i ] ) ) dp[i][j] = \min_{i < k < j} \left( dp[i][k] + dp[k][j] + (p[j] - p[i]) \right)
 d p [ i ] [ j ] = i < k < j min  ( d p [ i ] [ k ] + d p [ k ] [ j ] + ( p [ j ] − p [ i ]) ) 
于是这个问题可以不断分解,直到子问题的规模足够小(例如,当 i + 1 = j i + 1 = j i + 1 = j 最优子结构  的性质,可以使用动态规划法求解。
算法设计 
算法步骤 
初始化与排序: p p p L L L 
 
建立动态规划表: d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] p [ i ] p[i] p [ i ] p [ j ] p[j] p [ j ] 
 
填充动态规划表: i i i j j j k k k i < k < j i<k<j i < k < j k k k d p [ i ] [ j ] dp[i][j] d p [ i ] [ j ] 
 
返回最终结果: d p [ 0 ] [ n + 1 ] dp[0][n + 1] d p [ 0 ] [ n + 1 ] 
 
 
复杂度分析 
时间复杂度分析 
对n n n O ( n 2 ) O(n^2) O ( n 2 )  
建立dp数组的时间复杂度为 O ( n 3 ) O(n^3) O ( n 3 ) l e n len l e n O ( n ) O(n) O ( n ) i i i O ( n ) O(n) O ( n ) i , j i,j i , j k k k O ( n ) O(n) O ( n )  
 
于是,总体的时间复杂度为 O ( n 3 ) O(n^3) O ( n 3 ) 
空间复杂度分析 
上述算法使用了一个大小为 O ( n 2 ) O(n^2) O ( n 2 ) d p dp d p O ( n 2 ) O(n^2) O ( n 2 ) 
算法实现 
定义类 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 #include  <iostream>  #include  <vector>  #include  <algorithm>  #include  <climits>  using  namespace  std;void  MinCost (int  L, int  n, int  *p)  sort (p + 1 , p + n + 1 );0 ] = 0 ;1 ] = L;int >> dp (n + 2 , vector <int >(n + 2 , 0 ));for  (int  len = 2 ; len <= n + 1 ; len++) {for  (int  i = 0 ; i + len <= n + 1 ; i++) {int  j = i + len;for  (int  k = i + 1 ; k < j; k++)min (dp[i][j], dp[i][k] + dp[k][j] + p[j] - p[i]);0 ][n + 1 ] << endl;
主函数 
1 2 3 4 5 6 7 8 9 10 11 12 int  main ()  int  L = 7 , n = 4 ;int  *p = new  int [n + 2 ];0 ] = 1 ;1 ] = 3 ;2 ] = 4 ;3 ] = 5 ;MinCost (L, n, p); delete [] p; return  0 ;
运行结果