动态规划之矩阵连乘最优化问题

1.问题描述

输入:,其中Ai是 pi-1 * pi 矩阵

输出:计算 A1*A2*...*An 的最小代价方法


2.算法分析

假设m(i,j)表示计算Ai~j的最小乘法数,那么m(i,j)就等价于min( m(i,k) + m(k+1,j) + pi-1*pk*pj ),因此当 i=j 时有m(i,j)=0.

初始化问题:将对角线上元素m(i,i)设置为0,然后沿对角线递推子结构。


3.代码实现

import numpy as np

# 矩阵乘法的阶数
matrix = np.array([[2,3],[3,5],[5,3],[3,2],[2,6]])

#参与乘法运算的矩阵数目
num = len(matrix)

# 存储矩阵乘法的代价
mlti_order = np.zeros(num*num).reshape(num,-1)

# 存储矩阵乘法的顺序,即k值
mlti_k = np.zeros(num*num).reshape(num,-1)

#预定义一个最大代价,在比较取不同K值时需要用到
INF = 1000

# 递推子结构
for r in range(num - 1): #由于主对角线已被初始化为0,因此还需要递推num-1个对角线,
    i = 0
    j = r + 1
    while (i < num - r) & (j < num): #对于第r+1条对角线求每个m(i,j)的值
        k=i
        mlti_order[i][j] = INF 
        while k < j: #对每个m(i,j),求某个k值使m(i,k)+m(k+1,j)+pi-1*pk*pj最小
            value = mlti_order[i][k] + mlti_order[k+1][j] + matrix[i][0]*matrix[k][1]*matrix[j][1]
            if value < mlti_order[i][j]:
                mlti_order[i][j] = value
                mlti_k[i][j] = k #保存这个K值
            k += 1
            
        i += 1
        j += 1


print '这些矩阵相乘的最小代价为:',mlti_order[0][num-1],
   
def printOrder(order, i, j):
    if i == j:
        print 'A',i+1,  
    else:
        print '(',
        k = int(order[i][j])
        printOrder(order, i, k)
        printOrder(order, k+1, j)
        print ')',

print ',运算顺序为:',printOrder(mlti_k, 0, num-1)

4.时间复杂性

-计算代价的时间:(r,i,k)三层循环,每层至多n-1步,为O(n^3)

-构造最优解的时间:O(n)

-总时间复杂度:O(n^3)


5.空间复杂性

-使用数组mlti_order 和 mlti_k来存放代价和解,为O(n^2)

你可能感兴趣的:(数据结构及基本算法设计思想)