动态规划算法的有效性依赖于问题本身所具有的两个重要性质:
1.最优子结构 当问题的最优解包含了其子问题的最优解时,称该问题具有最优子结构性质 2.子问题重叠 在使用递归算法自顶向下求解问题时,产生的子问题并不总是新问题,有些子问题被反复计算过,动态规划算法(自底向上)正是利用了子问题重叠性质,对每个子问题只解一次。
已知:给定n个矩阵{A1,A2,…,An},其中Ai与Ai+1是可乘的, 计算:这n个矩阵的连乘积A1A2…An所需要的乘法运算的次数的最小值。
矩阵相乘的条件:第一个矩阵的列数=第二个矩阵的行数
因为矩阵乘法符合结合律,所以在计算ABC时,有两种方案,即(AB)C和A(BC)。对于第一方案(AB)C,计算: 其乘法运算次数为:2×3 ×2=12 其乘法运算次数为:2×2×4=16。 乘法运算次数的总计算量为:12+16=28 ############################################################ 对第二方案 A(BC),计算 其乘法运算次数为:3×2×4=24 其乘法运算次数为:2×3×4=24。 乘法运算次数的总计算量为:24+24=48
由此可以知道,不同方案的乘法运算量可能相差很悬殊。
将矩阵连乘积AiAi+1…Aj 简记为A[i:j], 这里i≤j; 考察计算A[1:n]的最优计算次序。
设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,1≤k<n
则其相应完全加括号方式为(A1A2…Ak)(Ak+1Ak+2…An) 计算量(乘法计算的次数)=: A[1:k]的计算量+ A[k+1:n]的计算量+ A[1:k]和A[k+1:n]相乘的计算量
特征:计算A[1:n]的最优次序所包含的计算矩阵子链 A[1:k]和A[k+1:n]的次序也是最优的。 最优子结构的证明: (反证法) 如果A[1:k]不是最优,即存在1…k的另一种计算方法, 使得矩阵1…k连乘的次数小于A[1:k] 则, 意味着存在一个更优的计算次序,比A[1:n]更小 即 A[1:n]不是最优计算次序。 这与已知矛盾。矩阵相乘的条件:第一个矩阵的列数=第二个矩阵的行数
设计算A[i: j](1≤i≤j≤n)所需要的最少乘法次数为m[i][j],则原问题的最优值为m[1][n] 。
当i=j时,A[i: j]=Ai,因此,m[i][i]=0 , i=1,2,…,n当i<j 时,
(Ai的维数是Pi-1×Pi)
可以递归地定义m[i][j]为 k的位置只有 j-i 种可能
-最优值的计算次序
最优解的计算过程 1-6(i,j) ((A1A2A3A4)(A5A6)) 1-4(i,j) (A1(A2A3A4)) (A2(A3A4)) 5-6(i,j) …… 如果 i==j, 输出Ai 否则 , 输出( 计算 (i,s[i][j]) 计算(s[i][j]+1,j) 输出 )
void TraceBack(int i, int j) { if(i==j) cout<<"A "<< i; else { cout<<"("; TraceBack(i,s[i][j]); TraceBack(s[i][j]+1,j); cout<<")"; } }