1.问题描述
输入:<A1,A2, … ,An>,其中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)