动态规划之矩阵链乘法

今天下午笔试遇到了矩阵链乘法,谨在此总结一下。

分析

关于本题的分析,动态规划之矩阵链乘法理解 已经讲的很详细了,我在此仅简单总结一下:
A 1 ∗ A 2 A_1*A_2 A1A2生成一个维度是 [ p 0 , p 2 ] [p_0, p_2] [p0,p2]的矩阵 ( A 1 A_1 A1的维度为 [ p 0 , p 1 ] [p_0, p_1] [p0,p1] A 2 A_2 A2的维度为 [ p 1 , p 2 ] [p_1, p_2] [p1,p2]),共有 p 0 ∗ p 2 p_0*p_2 p0p2个元素,每个元素由 p 1 p_1 p1次乘法得到,因此一共算法复杂度 p 0 ∗ p 2 ∗ p 1 p_0*p_2*p_1 p0p2p1
同理,对于 A i k , A k , A k j A_ik, A_k,A_kj Aik,Ak,Akj这三个矩阵连乘,复杂度为 p i ∗ p k ∗ p j p_i*p_k*p_j pipkpj,因此对于从第 i i i个到第 j j j个矩阵连乘,其最小代价的递归式可以写成:
递归式
于是问题的关键就归结为如何选择 k k k,事实上这会存在很多重复计算的子结构,所以需要循环来找最小的代价,当k=i……j时k每对应一个值就得继续往下递归,此时又得循环一遍k,在其中就会有许多子问题重复计算了。
刚才我们分析的是采用自上向下的方法,而实际上动态规划使用的是自底向上的方法,它在划分中把一些明显代价大的,可以比较的pk掉,从而减少分析次数,避免子问题的重复计算。

代码

# s记录最优值m[i,j]对应的分割点k
# dp记录代价m[i,j]
def matrixChainOrder(p):
    n = len(p)
    m = [[0 for _ in range(n)] for _ in range(n)]
    s = [[0 for _ in range(n)] for _ in range(n)]
    for i in range(n):
        m[i][i] = 0
    for l in range(2, n):    # l 表示选定的链长
        for i in range(1, n-l+1):      # i 表示可以划定成多少种
            j = i+l-1     # j 表示划定的子链的末尾
            m[i][j] = float('inf')
            for k in range(i, j):    # 寻求最优k使得子结构最优
                q = m[i][k] + m[k+1][j] + p[i-1]*p[k]*p[j]
                if q < m[i][j]:
                    m[i][j] = q
                    s[i][j] = k
    return m, s

#输出矩阵链的最优括号化方法
def printOpt(s, i, j):
    if i == j:
        print("A"+str(i), end=' ')
    else:
        print("(", end=' ')
        printOpt(s, i, s[i][j])
        printOpt(s, s[i][j] + 1, j)
        print(")", end=' ')

if __name__ == '__main__':
    print("start=========")
    p = [30, 35, 15, 5, 10, 20, 25]
    m, s = matrixChainOrder(p)

    # print(m)
    # print(s)
    print("最优括号化方案为:")
    printOpt(s, 1, 6)
    print("")
    print("其标量乘法次数为:", m[1][6])

    print("Over=========")

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值