矩阵连乘问题 Python 动态规划

文章目录

    • 矩阵连乘问题的动态规划算法设计过程与实现
      • 1.算法设计
        • 1.1 构造最优值矩阵 ,并将断开位置记录在断开位置矩阵中
        • 1.2 根据断开位置矩阵计算得出最优解
      • 2. 算法实现-完整代码
      • 3. 程序测试
        • 输入值
        • 输出值
        • 测试结果


矩阵连乘问题的动态规划算法设计过程与实现

1.算法设计

  1. 首先应获取矩阵,此算法主要计算最优值与最优解,暂不考虑矩阵不可乘情况。因此用户输入的矩阵默认是可乘的,并以此做相应计算
  2. 计算用户输入矩阵长度,同时初始化最优值矩阵 m m m 和最优解矩阵 s s s
  3. 进行相应计算
  4. 输出最优解和最优值

1.1 构造最优值矩阵 ,并将断开位置记录在断开位置矩阵中

def matrixChain():
    """
    计算最优值关系矩阵

    :return: None
    """
    for i in range(2, n + 1):  # 对角线
        for r in range(1, n - i + 2):  # 行
            c = r + i - 1  # 列
            # 找到m[r][c]的最小值并计入列表
            m[r][c] = m[r][r] + m[r + 1][c] + p[r - 1] * p[r] * p[c]
            s[r][c] = r
            # 从r+1道c-1寻找m[r][c]的最小值
            for j in range(r + 1, c):
                t = m[r][j] + m[j + 1][c] + p[r - 1] * p[j] * p[c]
                if t < m[r][c]:
                    m[r][c] = t
                    # 将子序列r-c段中j的位置存入s,此处断开可以得到最优解
                    s[r][c] = j

1.2 根据断开位置矩阵计算得出最优解

def traceBack(r: int, c: int) -> None:
    """
    根据s记录的各个子段的最优解,将其输出

    :param r: 行
    :param c: 列
    :return: None
    """
    if r == c:
        return
    traceBack(r, s[r][c])
    traceBack(s[r][c] + 1, c)
    # 描述括号位置
    print(f'左括号 : A{s[r][c]}之前 \t 与之对应的右括号 : A{c}之后')

2. 算法实现-完整代码

print('请输入连乘矩阵的维数:')
print('示例:A[2*5],B[5*10],C[10*2]')
print('应输入:2 5 10 2(使用空格隔开)')
p = list(map(int, input().split()))  # 获取用户输入连乘矩阵维数
n = len(p) - 1  # 计算用户输入矩阵个数
m = [[0 for i in range(n + 1)] for j in range(n + 1)]  # 初始化最优解列表
s = [[0 for i in range(n + 1)] for j in range(n + 1)]  # 初始化断开位置列表


def matrixChain():
    """
    计算最优值关系矩阵

    :return: None
    """
    for i in range(2, n + 1):  # 对角线
        for r in range(1, n - i + 2):  # 行
            c = r + i - 1  # 列
            # 找到m[r][c]的最小值并计入列表
            m[r][c] = m[r][r] + m[r + 1][c] + p[r - 1] * p[r] * p[c]
            s[r][c] = r
            # 从r+1道c-1寻找m[r][c]的最小值
            for j in range(r + 1, c):
                t = m[r][j] + m[j + 1][c] + p[r - 1] * p[j] * p[c]
                if t < m[r][c]:
                    m[r][c] = t
                    # 将子序列r-c段中j的位置存入s,此处断开可以得到最优解
                    s[r][c] = j


def traceBack(r: int, c: int) -> None:
    """
    根据s记录的各个子段的最优解,将其输出

    :param r: 行
    :param c: 列
    :return: None
    """
    if r == c:
        return
    traceBack(r, s[r][c])
    traceBack(s[r][c] + 1, c)
    # 描述括号位置
    print(f'左括号 : A{s[r][c]}之前 \t 与之对应的右括号 : A{c}之后')


matrixChain()
traceBack(1, n)
print(f'乘法次数 : {m[1][n]}')

3. 程序测试

输入值

30 35 15 5 10 20 25

输出值

左括号 : A2之前 	 与之对应的右括号 : A3之后
左括号 : A1之前 	 与之对应的右括号 : A3之后
左括号 : A4之前 	 与之对应的右括号 : A5之后
左括号 : A5之前 	 与之对应的右括号 : A6之后
左括号 : A3之前 	 与之对应的右括号 : A6之后
乘法次数 : 15125

测试结果

程序运行正确且运行结果符合预期。

你可能感兴趣的:(日常学习随笔,算法,python,动态规划)