算法之路__19、動態規劃之矩陣鏈相乘

動態規劃之矩陣鏈相乘

問題描述

給定n個矩陣{A1,A2,…,An},其中Ai與Ai+1是可乘的,i=1,2 ,…,n-1。
確定計算矩陣連乘積的計算次序,使得依此次序計算矩陣連乘積需要的數乘次數最少。

思路:

構造遞歸解

設m[i,j]爲矩陣鏈Ai…Aj的最優解的代價,則

       ┌ 0    如果i = j

m[i,j] = │

      └ min(i≤k<j) {m[i,k] + m[k+1,j] + Ai.row*Ak.col*Aj.col}  如果i < j

假如n=6 則m矩陣爲:
(上三角)
首先在對角線0中,每個鏈僅由一個矩陣的組成,沒有數量乘法,因此這個對角線填0。
接着,對角線1由兩個連續的矩陣相乘的耗費來填充。如C[2][3]用M2M3M2M3的乘法耗費來填。
餘下的對角線根據上面的遞推式和先前存儲在表中值來填。舉例來說,C[2][5]的值爲以下三個耗費的最小值:

  • (1)計算M2,2M2,2的耗費(即C[2][2])加上計算M3,5M3,5(即C[3][5])的耗費,再加上M2,2M2,2乘以M3,5M3,5的耗費。
  • (2)計算M2,3M2,3的耗費(即C[2][3])加上計算M4,5M4,5(即C[4][5])的耗費,再加上M2,3M2,3乘以M4,5M4,5的耗費。
  • (3)計算M2,4M2,4的耗費(即C[2][4])加上計算M5,5M5,5(即C[5][5])的耗費,再加上M2,4M2,4乘以M5,5M5,5的耗費。
# 輔助表 m 保存代價 m[i,j]
# 輔助表 s 記錄最優值 m[i,j]對應的分割點 k
def maxChain(p):
    n = len(p)
    m = [[0 for i in range(n)] for j in range(n)]
    s = [[0 for i in range(n)] for j in range(n)]


    for l in range(2,n):  # 對角線

        for i in range(1,n-l+1):  # 行
            j = i+l-1
           # m[i][j] = 9999999999
            for k in range(i,j):
                if(k == i):
                    m[i][j] = m[i][k] + m[k+1][j] + p[i-1] * p[k] * p[j]
                    s[i][j] = k

                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 printOpt(s, i, j):
    if i == j:
        print("A", i, end='')
    else:
        # print("(", end="")
        print("(", end='')
        printOpt(s, i, s[i][j])
        printOpt(s, s[i][j]+1, j)
        print(")", end='')


print("start=========")

# p = [30, 35, 15, 5, 10, 20, 25]
p = [3, 5, 6, 7, 4]
m, s = maxChain(p)

# print(m)
# print(s)
print("最優括號化方案爲:")

printOpt(s, 1, 4)

print("")
print("其標量乘法次數爲:", m[1][4])

print("Over=========")
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章