1. 程式人生 > >動態規劃之矩陣連乘最優化問題

動態規劃之矩陣連乘最優化問題

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)