【算法导论】动态规划之矩阵链乘法Python实现

前提

  • 浏览了书中的整体流程,对代码的一些部分没太明白

问题定义

求多个矩阵相乘的最优计算顺序,使得计算量最低

编程

  • 看转移方程的定义后将矩阵的行列大小定义为一个列表,本文定义方式p = [30, 35, 15, 5, 10, 20, 25] ,对矩阵的行列表示,说明有5个矩阵,第一个的阶数为3035, 第二个为3515, 第三个为15*5,以此类推
  • 只对上三角进行填表,填入顺序为从左到右,从下到上
  • 下列表格列出了表的插入顺序
1 3 6
2 5
4

代码

p = [30, 35, 15, 5, 10, 20, 25] 
def matrix_chain_order(p):
    n = len(p) - 1   # 矩阵个数
    m = [[0 for i in range(n)] for j in range(n)] 
    s = [[0 for i in range(n)] for j in range(n)] # 用来记录最优解的括号位置
    for l in range(1, n): # 控制列,从左往右
        for i in range(l-1, -1, -1):  # 控制行,从下往上
            m[i][l] = float('inf') # 保存要填充格子的最优值
            for k in range(i, l):  # 控制分割点
                q = m[i][k] + m[k+1][l] + p[i]*p[k+1]*p[l+1]
                if q < m[i][l]:
                    m[i][l] = q
                    s[i][l] = k
    return m, s

def print_option_parens(s, i, j):
    if i == j:
        print('A'+str(i+1), end='')
    else:
        print('(', end='')
        print_option_parens(s, i, s[i][j])
        print_option_parens(s, s[i][j]+1, j)
        print(')', end='')

r, s = matrix_chain_order(p)
print_option_parens(s, 0, 5)

代码遇到的坑

  • m = [[0 for i in range(n)] for j in range(n)]其实最先的定义方式为m=[[0] * n ] * n,但是这样会产生一个很严重的问题
>>> lists = [[]] * 3
>>> lists
[[], [], []]
>>> lists[0].append(3)
>>> lists
[[3], [3], [3]]
  • 得到的s数组(列表)和书中是不同的,每个数都会比书中少1,如果要求统一,可以将s[i][l] = k改成s[i][l] = k+1即可
  • 代码中设计到三个循环,而且循环是环环相扣,为锻炼这种环环相扣的编程能力,建议先练习输出一个二维数组上有规律排列的输出顺序,如二维数组如下
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
- 输出1 2 6 3 7 11 4 8 12 16
- 输出1 6 2 11 7 3 16 12 8 4(本题的输出顺序)
- 输出1 6 2 3 7 11 16 12 8 4
- 输出上述三种方式的逆顺序

猜你喜欢

转载自blog.csdn.net/u013887652/article/details/88575291