动态规划详解(第三讲)——矩阵链相乘

这篇博客详细讲解了动态规划在解决矩阵链相乘问题中的应用,通过递推关系式、填表方法和伪代码阐述了如何寻找最优乘法顺序以减少运算量。并分析了算法的时间和空间复杂度。

这类题目体现了DP的实质,也是经典问题。(•̀˓◞•́)

假设我们要用标准的矩阵乘法计算M1M1M2M2M3M3的乘积M1M2M3M1M2M3,这三个矩阵的维数分别是2x10,10x2,2x10。

  • 如果我们先把M1M1M2M2相乘,然后把结果和M3M3相乘,即M1M2M3((M1M2)M3)。那么要进行2x10x2+2x2x10=80次乘法;
  • 如果我们先乘M2M2M3M3,结果再与M1M1相乘,即M1M2M3(M1(M2M3))。那么数量乘法的次数就变成了:10x2x10+2x10x10=400。

可见,矩阵链相乘时的顺序不同,运算量也不同。而我们的目的是找到一种乘法顺序使得运算量最小。


递推关系式

        我们注意到,对于矩阵链M1M2...MiM1M2...Mi,矩阵MiMi的列数一定等于矩阵Mi+1Mi+1的行数(1i<n1≤i<n),这是由矩阵乘法的定义决定的。
        因此,对于一个矩阵链,我们指定每个矩阵的行数和最右面矩阵MnMn的列数就可以了。假设有n+1维数r1,r2,...,rn+1r1,r2,...,rn+1,这里riri表示矩阵MiMi的行数(1in1≤i≤n),rn+1rn+1表示最矩阵MnMn的列数。
        以后,我们用Mi,jMi,j来记MiMi+1...MjMiMi+1...Mj的乘积。用C[i][j]C[i][j]来记录链Mi,jMi,j数量乘法的次数。
        对于给定的一对索引iij1i<jnMi,jMi,j可用如下方法计算:

  • kki+1jj之间的一个索引,索引k把矩阵链Mi,jMi,j分成了两部分:Mi,k1=MiMi+1...Mk1Mi,k−1=MiMi+1...Mk−1Mk,j=MkMk+1...MjMk,j=MkMk+1...Mj。所以Mi,j=Mi,k1Mk,jMi,j=Mi,k−1Mk,j

            用这种方法计算Mi,jMi,j的耗费(即数量乘法的次数),是计算Mi,k1Mi,k−1的耗费加上计算Mk,jMk,j的耗费再加上Mi,k1Mi,k−1乘以Mk,jMk,j的耗费(它是rirkrj+1rirkrj+1)。

    我们需要遍历kk,找到使乘法MiMi+1...Mj所需的数量乘法最小的kk值,我们有以下递推式:

    C[i][j]=Mini<kjMini<k≤j{C[i][k1]+C[k][j]+rirkrj+1}{C[i][k−1]+C[k][j]+rirkrj+1}

        为了找出M1M2..MnM1M2..Mn的乘法次数,我们只需要解递推式:

C[1][n]=C[1][n]=Min1<knMin1<k≤n{C[1][k1]+C[k][n]+rirkrn+1}{C[1][k−1]+C[k][n]+rirkrn+1}

填表

假设我们要求n=6n=6个矩阵相乘。考虑下图:
这里写图片描述

对角线dd用乘出各种d+1个相继矩阵的最小耗费填满。特别地,对角线5恰好由一项组成,它表示6个矩阵相乘的最小耗费,这就是我们要求的结果。
我们从对角线0开始,到对角线5为止,沿着对角线填充这个三角形表。

  • 首先在对角线0中,每个链仅由一个矩阵的组成,没有数量乘法,因此这个对角线填0。
  • 接着,对角线1由两个连续的矩阵相乘的耗费来填充。如C[2][3]用M2M3M2M3的乘法耗费来填。
  • 余下的对角线根据上面的递推式和先前存储在表中值来填。举例来说,C[2][5]的值为以下三个耗费的最小值:
    – (1)计算M2,2M2,2的耗费(即C[2][2])加上计算M3,5M3,5(即C[3][5])的耗费,再加上M2,2M2,2乘以M3,5M3,5的耗费。
    – (2)计算M2,3M2,3的耗费(即C[2][3])加上计算M4,5M4,5(即C[4][5])的耗费,再加上M2,3M2,3乘以M4,5M4,5的耗费。
    – (3)计算M2,4M2,4的耗费(即C[2][4])加上计算M5,5M5,5(即C[5][5])的耗费,再加上M2,4M2,4乘以M5,5M5,5的耗费。

伪代码

下面我们给出算法的伪代码实现
MATCHAIN
输入:n个矩阵的链的维数对应于正整数数组r[1...n+1]r[1...n+1],其中,r[1...n]r[1...n]是n个矩阵的行数,r[n+1]r[n+1]MnMn的列数。
输出:n个矩阵相乘的数量乘法的最小次数。

for i=1 to n {填充对角线d0}
    C[i,i]=0;
end for
for d=1 to n-1 {填充对角线d1到dn-1}
    for i=1 to n-d {填充对角线di的项目}
        j=i+d
        comment:下列三行计算C[i,j]
        C[i,j]=inf
        for k=i+1 to j
            C[i,j]=Min{C[i,j],C[i,k-1]+C[k,j]+r[i]*r[k]*[j+1]
        end for
    end for
end for
return C[1,n]


时空复杂度

对于某个常数c>0,算法的运行时间正比于:

d=1n1i=1ndk=1dc=cn3cn6∑d=1n−1∑i=1n−d∑k=1dc=cn3−cn6

因此算法的时间复杂度是Θ(n3)Θ(n3)

显然,算法所需要的内存空间取决于所需要的三角数组的大小,也就是Θ(n2Θ(n2)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值