动态规划---矩阵链相乘

问题描述

给定若干个矩阵,寻找最优的相乘次序,使得乘法运算的次数最少,并输出对应的最少运算次数。比如现有三个矩阵ABC,维数分别为A:2×10B:10×2, C:2×10 。虽然(AB)C=A(BC) 结果是相等的,即与相乘次序没有关系。但是(AB)C乘法运算的次数为2×10×2+2×2×10=802×10×2+2×2×10=80,而A(BC)为10×2×10+2×10×10=40010×2×10+2×10×10=400,显然(AB)C的运算次数更少,即效率更高。

思路

求解的关键在于如何将问题分解为若干子问题。我们想象在各个矩阵之间可以放上隔板,那么只要先分别求解左和右的最少乘法次数,再将隔板左右的两部分相乘,就可以得到当前分隔方法的最优解,最后通过比较各种分隔方法,就能得到当前长度的最优解,如下图中四种分隔中我们取最少的次数,即为长度5(5个连续矩阵)的最优解。由于分隔后的长度必定小于当前长度,如此处的子问题长度必定小于5,而子问题已经在之前的迭代过程求得,无需重复计算。通过下一部分的迭代过程展示能有更直观的理解。

思路1:递归,把原数组从i到j-1做切分,计算切分之后两个子序列连乘的乘积之和和两个子序列总体的乘积

时间复杂度指数级,会有重复计算

 

代码如下:

#递归
def MatrixChainOrder(p,i,j):
    if i == j:
        return 0
    mins = 2 ** 32

    k = i
    while k < j:
        #count分成三份,从k做切分,[i,k]+[k+1,j]+总体
        count = MatrixChainOrder(p,k+1,j) + MatrixChainOrder(p,i,k) + p[i-1] * p[k] * p[j]
        #p[i-1] * p[k] * p[j]是两个子序列连乘的乘积矩阵再相乘的计算量
        print(i,k,j,count)

        if count < mins:
            mins = count
        k += 1
    return mins

 

 

思路2:动态规划

自下而上的方式构造临时数组来保存子问题的中间结果,避免重复计算

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

 

迭代过程:

为了更直观的理解,下图和上面是等效的。(符号说明:m[a,b]代表从序号为a到序号为b的矩阵链所需的最少乘法次数,特别地,m[a,a]代表a号矩阵本身,很明显m[a,a]=0。)

先计算第二行(m[1,2],m[2,3],m[3,4],m[4,5]),然后第三行(m[1,3],m[2,4],m[3,5]),....

 

算法实现

arr[]数组用于记录矩阵链信息,其中n号矩阵对应的维数是arr[n-1]*arr[n]。动态规划的核心算法利用3个for循环,最外层控制矩阵链长度,下一层控制起始点,再下一层控制隔板的位置。最后左右合并的时候注意下标的选择,如下图所示。

 

代码如下:

#动态规划,自下而上
def MatrixChainOrder2(p,n):
    cost = [([None]*n) for i in range(n)]
    i = 1
    while i < n:
        cost[i][i] = 0
        i += 1
    cLen = 2
    #i=start,j=end,cLen=length
    while cLen < n:
        i = 1
        while i < n-cLen+1:
            j = i + cLen - 1
            print(i,j,cLen)
            cost[i][j] = 2 ** 31
            k = i
            while k <= j-1:
                q = cost[i][k] + cost[k+1][j] + p[i-1]*p[k]*p[j]
                if q < cost[i][j]:
                    cost[i][j] = q
                k += 1
            i += 1
        cLen += 1
    # print(cost)
    return cost[1][n-1]

 

 结果如下:

1 2 2
2 3 2
3 4 2
4 5 2
1 3 3
2 4 3
3 5 3
1 4 4
2 5 4
1 5 5
res 11875

 

转载于:https://www.cnblogs.com/nxf-rabbit75/p/10450009.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值