动态规划典型题之——矩阵链乘法

动态规划是算法分析与设计中一种重要的算法。其核心思想是将大问题划分为小问题进行解决,从而一步步获取最优解的处理算法。


一、矩阵链相乘问题

例: 令P=<50,35,25,10,60,70,3,5,10>,相对应的矩阵链是:A1(50*35), A2(35*25), A3(25*10), A4(10*60), A5(60*70), A6(70*3), A7(3*5), A8(5*10), 括号内为矩阵的维度,请⽤动态规划算法确定⼀种乘法⽅式,使得A1*A2*A3*A4*A5*A6*A7*A8总的基本运算量(只算乘法,不算加法)最少。

二、求解

1.构建备忘录

备忘录是动态规划算法常用的工具,用来存储子问题得到的最优值并递归的更新其值,直到寻找到全局最优值为止。MatrixChain函数中定义了两个相同大小(n*n)的矩阵M和S,n为矩阵数量。
M(i,j)表示从第i+1个矩阵到第j+1个矩阵链的最少运算总量,故M(0,n-1)即表示了整个矩阵链的最少运算总量。
S(i,j)表示从第i+1个矩阵到第j+1个矩阵链的分割位置,因为每一矩阵链都可看作是两个矩阵链分别运算后的乘积。此矩阵可用于回溯矩阵相乘的顺序。

# 求最优值,记录备忘录
def MatrixChain(p):
    n = len(p) - 1
    # 存最优值
    m = np.zeros((n, n))
    # 存最优决策
    s = np.zeros((n, n))
    # R 表示矩阵链长度 从2开始
    for r in range(2, n + 1):
        # 从第i个矩阵Ai开始,长度为r,循环次数为n-r+1
        for i in range(n - r + 1):
            j = i + r - 1  # 当前矩阵端(Ai-Aj)起始为Ai 结尾为Aj
            # 初始化
            m[i][j] = m[i + 1][j] + p[i] * p[i + 1] * p[j + 1]
            s[i][j] = i
            # 比较寻最小值
            for k in range(i + 1, j):
                t = m[i][k] + m[k + 1][j] + p[i] * p[k + 1] * p[j + 1]
                if t < m[i][j]:
                    m[i][j] = t
                    s[i][j] = k
    return m, s

2.回溯

回溯函数如下,采用递归方法构造:

# 记录最优决策并构造最优解
res = []
def Traceback(i, j):
    if i == j:
        res.append('A' + str(i))
    else:
        res.append('(')
        Traceback(i, int(s[i][j]))
        Traceback(int(s[i][j] + 1), j)
        res.append(')')

结果展示

矩阵链为:P=<50,35,25,10,60,70,3,5,10>
备忘录的值为

[[     0.  43750.  26250.  56250. 103250.  23025.  23775.  24675.]
 [     0.      0.   8750.  29750.  75250.  17775.  18300.  18975.]
 [     0.      0.      0.  15000.  59500.  15150.  15525.  16050.]
 [     0.      0.      0.      0.  42000.  14400.  14550.  14850.]
 [     0.      0.      0.      0.      0.  12600.  13500.  14550.]
 [     0.      0.      0.      0.      0.      0.   1050.   2250.]
 [     0.      0.      0.      0.      0.      0.      0.    150.]
 [     0.      0.      0.      0.      0.      0.      0.      0.]] 

可见最小值为24675.0
决策矩阵为:

[[0. 0. 0. 2. 2. 0. 5. 5.]
 [0. 0. 1. 2. 2. 1. 5. 5.]
 [0. 0. 0. 2. 2. 2. 5. 5.]
 [0. 0. 0. 0. 3. 3. 5. 5.]
 [0. 0. 0. 0. 0. 4. 5. 5.]
 [0. 0. 0. 0. 0. 0. 5. 5.]
 [0. 0. 0. 0. 0. 0. 0. 6.]
 [0. 0. 0. 0. 0. 0. 0. 0.]]

最终矩阵链的相乘顺序为:((A0(A1(A2(A3(A4A5)))))(A6A7))

  • 0
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
动态规划矩阵链乘问题是指给定一系列矩阵,求解它们相乘的最少乘法次数。根据引用\[2\]中的解释,我们可以使用一个二维数组m来表示矩阵相乘所需要的最少乘法次数。其中,m\[i, j\]表示从矩阵i到矩阵j相乘所需要的最少乘法次数。 根据引用\[3\]中的思路,当只有一个矩阵时,乘法次数为0;当有两个矩阵时,乘法次数为矩阵行列直接相乘的结果。对于三个及以上的矩阵,我们可以通过动态规划的方式来求解最少乘法次数。 具体的动态规划算法如下: 1. 初始化二维数组m的对角线元素为0,表示只有一个矩阵时的乘法次数为0。 2. 从长d=2开始,逐步增加长,计算m\[i, j\]的值。对于每个长d,遍历所有可能的分割点k,计算m\[i, j\]的值。具体计算方式为:m\[i, j\] = min{m\[i, k\] + m\[k+1, j\] + a\[i\]*a\[k\]*a\[j+1\]},其中a\[i\]表示第i个矩阵的行数,a\[j+1\]表示第j+1个矩阵的列数。 3. 最终,m\[1, n\]即为所求的最少乘法次数,其中n为矩阵的长度。 通过以上算法,我们可以得到矩阵相乘的最少乘法次数。这个问题动态规划解法可以有效地减少重复计算,提高计算效率。 #### 引用[.reference_title] - *1* *2* *3* [动态规划——矩阵相乘](https://blog.csdn.net/Wu_L7/article/details/124327310)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值