矩阵连乘详解

动态规划算法与分治法类似,其基本思想也是将待求解问题分解成若干个子问题。

动态规划基本步骤

•找出最优解的性质,并刻划其结构特征。
•递归地定义最优值。
•以自底向上的方式计算出最优值。
•根据计算最优值时得到的信息,构造最优解。

矩阵相乘只有在第一个矩阵的列数和第二个矩阵的行数相同时才有定义,设有矩阵M1,M2,M3,M4

其维数分别是30×35, 35×15, 15×5 5×10,现要求出这4个矩阵相乘的结果。若矩阵A的维数是m×n,矩阵B的维数是n×r,则AB相乘后所得矩阵AB的维数是m×r。按照矩阵相乘的定义,求出矩阵AB中的一个元素需要做n次乘法(及q-1次加法)。这样,要计算出AB就需要做n×m×r次乘法。为简单起见,且由于加法比同样数量的乘法所用时间要少得多,故这里我们暂不考虑加法的计算量。因矩阵连乘满足结合律,故计算矩阵连乘的方式可以有多种。

例如

M3M45*15*10=750;共750次乘法 

M2(M3M4):35*15*10=5250;共5250次乘法 

M1(M2(M3M4)):30*35*10=10500;共10500次乘法 

(M1(M2M3))30*35*5=5250共5250次乘法 

(M1(M2M3))M430*5*10=1500;共1500次乘法 


求矩阵连乘最小乘法次数 

   

将矩阵连乘积Ai,Ai+1,...,Aj  简记为A[i:j] ,这里i≤j ,考察计算A[i:j]的最优计算次序。设这个计算次序在矩阵

Ak和Ak+1之间将矩阵链断开,i≤k

计算量:A[i:k]的计算量加上A[k+1:j]的计算量,再加上A[i:k]和A[k+1:j]相乘的计算量

计算A[i:j]的最优次序所包含的计算矩阵子链A[i:k]和A[k+1:j]的次序也是最优的。矩阵连乘计算次序问题的最优解包含着其子问题的最优解。这种性质称为最优子结构性质。问题的最优子结是该问题可用动态规划算法求解的显著特征。
设计算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


可以递归地定义m[i,j]为:


例如我们来计算此四个矩阵的最小连乘次数 30×35, 35×15, 15×5 5×10和10*25

m[2,4]=min{m[2,k]}+m[k+1,4]+P1PkP4}其中分K的不同取值来找最小的,此时k只能取2,3。k的位置只有j-i可能

4-2=2,所以k只有2种可能

矩阵 M1 M2 M3 M4 M5
行数*列数 30*35 35*15 15*5 5*10 10*25
P下标 0 1 2 3 4
P值 30 35 15 5 10

m[2,4]=m[2,2]+m[3,4]+P1P2P4=0+m[3,3]+m[4,4]+P2P3P4+P1P2P4 =0+0+0+15*5*10+35*15*10=750+5250=6000

或者=m[2,3]+m[4,4]+P1P3P4=m[2,2]+m[3,3]+P1P2P3+0+P1P3P4=0+0+35*15*5+0+35*5*10=2625+1750=4375

在程序编写中通过比较大小得出最小次数,主要代码实现如下: 

  

      for(int i =1; i <= n; i++) m[i][i] = 0;

      for(int r =2; r <= n; r++)

         for(int i =1; i <= n - r+1; i++) {

            int j=i+r-1;

            m[i][j] = m[i+1][j]+p[i-1]*p[i]*p[j];

            s[i][j] = i;

            for(int k =i+1; k < j; k++) {

               int t =m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j];

               if(t < m[i][j]) {

                 m[i][j] = t;

                 s[i][j] = k;}


 




你可能感兴趣的:(算法分析)