算法导论程序36--动态规划(矩阵链)

本节的例子是求解矩阵链相乘问题的动态规划算法。

给定一个n个矩阵的序列(矩阵链)<A1,A2,...,An>,我们希望计算它们的乘积A1A2...An。

由于矩阵乘法满足结合律,因此任何加括号的方法都会得到相同的计算结果,我们称有如下性质的矩阵乘积链为完全括号话的。它是单一矩阵,或者是两个完全括号花的矩阵乘积链的积,且已外加括号。

例如,如果矩阵链为<A1,A2,A3,A4>,则共有5种完全括号化的矩阵乘积链。


对矩阵链加括号的方式会对乘积计算的代价产生巨大的影响。

矩阵链乘法问题可以描述如下:给定n个矩阵的链<A1,A2,...,An>,矩阵Ai的规模为求完全括号化方案,使得计算乘积A1A2,..An所需标量乘法次数最少。


我们的目标不是计算矩阵的乘积,而是确定代价最低的计算顺序。

假设p(n)表示可供选择的括号花方案的数量。当n>=2时,完全括号化的矩阵乘积可描述为两个完全括号化的部分积相乘的形式。而两个部分积的划分点在第k个矩阵和第k+1个矩阵之间。k为1,2,,,n-1中的任意一个值。


上面的递归公式的结果为

因此,括号化的方案的数量与n呈指数关系。通过暴力搜索穷尽所有可能的括号化的方案来寻找最优方案,是一个糟糕的策略!!!


应用动态规划方法

4个步骤:

1.刻画一个最优解的结构特征。

2.递归地定义最优解的值。

3.计算最优解的值,通常采用自底向上的方法。

4.利用计算出的信息构造一个最优解。


步骤一:动态规划的第一步是寻找最优子结构。然后就可以利用这种子结构从子问题的最优解构造出原问题的最优解。





步骤二:一个递归求解方案

下面用子问题的最优解来递归地定义原问题最优解的代价。




步骤三:计算最优代价

def matrix_chain_order(p):
    n=len(p)-1
    m=[[0 for j in range(0,n+1)] for i in range(0,n+1)]
    s=[[0 for j in range(0,n+1)] for i in range(0,n+1)]
    for l in range(2,n+1):
        for i in range(1,n-l+2):
            j=i+l-1
            m[i][j]=float("inf")
            for k in range(i,j):
                q=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j]
                if q<m[i][j]:
                    m[i][j]=q
                    s[i][j]=k
    return m,s

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

if __name__=='__main__':
    p=[30,35,15,5,10,20,25]
    m,s=matrix_chain_order(p)
    print_optimal_parens(s,1,6)

运行:

>>> 
 RESTART: D:\Program Files\Python\test\algorithms\算法导论\36-matrix-chain-order.py 
((A 1(A 2A 3))((A 4A 5)A 6))
>>> for i in range(1,7):
	for j in range(1,7):
		print(m[i][j],' ',end='')
	print()

	
0  15750  7875  9375  11875  15125  
0  0  2625  4375  7125  10500  
0  0  0  750  2500  5375  
0  0  0  0  1000  3500  
0  0  0  0  0  5000  
0  0  0  0  0  0  
>>> for i in range(1,7):
	for j in range(1,7):
		print(s[i][j],' ',end='')
	print()

	
0  1  1  3  3  3  
0  0  2  3  3  3  
0  0  0  3  3  3  
0  0  0  0  4  5  
0  0  0  0  0  5  
0  0  0  0  0  0  





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值