博主根据老师讲义,自己手撸代码,若有错误,多谢指出。 直接上代码
目录
0 讲义
0.1 问题定义
0.2 问题分析
0.3 动态规划算法
0.4 伪代码
迭代实现动态规划 code:迭代实现
0.5 举个例子说明
备忘录里的数据在代码里,应该是博主手绘的那个样子。
m[2,4]的意思是,矩阵A2连乘到A4,即A2*A3*A4.
标记函数的输出:code:输出连乘顺序
1 代码
注意,讲义中的矩阵序号从1开始,代码中矩阵序号从0开始。
1.1 code:迭代实现
import numpy as np
"""
对于矩阵{A_0,A_1,... ...,A_n}
对应阶数{P_0,P_1,... ...,P_n,P_n+1}
它们的行列表达为 A_0 = P_0 * P_1
"""
def matrixChain(p, n=1, memo=None, seq=None):
size = len(p)-n # 子问题个数
if n==1: # 长度为1的矩阵链,数乘次数为0
memo = np.zeros([size,size], dtype=int)
seq = np.zeros([size,size], dtype=int)
else: # 其他长度
for i in range(size): # 左边界
j = i+n-1 # 右边界
for k in range(i,j): # 分界位置
t = memo[i,k] + memo[k+1,j] + p[i]*p[k+1]*p[j+1]
if t < memo[i,j] or memo[i,j]==0:
memo[i,j] = t
seq[i,j] = k
# 进入n+1
if n < len(p)-1:
matrixChain(p, n+1, memo,seq)
return memo, seq
"""
memo =
[[ 0 15750 7875 9375 11875]
[ 0 0 2625 4375 7125]
[ 0 0 0 750 2500]
[ 0 0 0 0 1000]
[ 0 0 0 0 0]]
seq =
[[0 0 0 2 2]
[0 0 1 2 2]
[0 0 0 2 2]
[0 0 0 0 3]
[0 0 0 0 0]]
"""
1.2 code:输出连乘顺序
def prtSeq(seq, i, j):
size = j-i+1
if size ==1:
return 'A%d'%i
else: # 至少有三个元素,才要考虑数乘顺序
k = seq[i,j] # 分界位置
res = ''
res += '('+ prtSeq(seq, i, k)
res += prtSeq(seq, k+1, j) + ')'
return res
"""
res = ((A0(A1A2))(A3A4))
注意,输出结果会比正确结果多一对()
"""
1.3 code:主函数
n = eval(input('请输入矩阵个数:'))
p = eval(input('请输入矩阵尺寸:'))
m,seq = matrixChain(p)
res = prtSeq(seq,0,n-1)
print('最佳数乘次序:%s, 此时数乘次数:%d'%(res[1:-1], m[0,-1]))
"""
请输入矩阵个数:5
请输入矩阵尺寸:30,35,15,5,10,20
最佳数乘次序:(A0(A1A2))(A3A4), 此时数乘次数:11875
"""