思考:
三个矩阵A,B,C的阶分别是 a 0 ∗ a 1 , a 1 ∗ a 2 , a 2 ∗ a 3 a_0*a_1,a_1*a_2,a_2*a_3 a0∗a1,a1∗a2,a2∗a3 ,从而(AxB)xC和Ax(BxC)的乘法次数是 a 0 ∗ a 1 ∗ a 2 + a 0 ∗ a 2 ∗ a 3 , a 1 ∗ a 2 ∗ a 3 + a 0 ∗ a 1 ∗ a 3 a_0*a_1*a_2+a_0*a_2*a_3,a_1*a_2*a_3+a_0*a_1*a_3 a0∗a1∗a2+a0∗a2∗a3,a1∗a2∗a3+a0∗a1∗a3,二者一般是不相等的。则对于n个矩阵的连乘, A 1 ∗ A 2 ⋯ ∗ A n A_1*A_2\dots*A_n A1∗A2⋯∗An,如何改变计算次序,使得乘法次数计算量最小呢?
例如:
A1={30x35} ; A2={35x15} ;A3={15x5} ;A4={5x10} ;A5={10x20} ;A6={20x25} ;
结果为:((A1(A2A3))((A4A5)A6)) 最小的乘次为15125。
思路:
设A[i:j]为矩阵 A i ∗ A i + 1 ⋯ ∗ A j A_i*A_{i+1}\dots*A_j Ai∗Ai+1⋯∗Aj的连乘积,即从Ai到Aj的连乘积,其中,0 <= i <= j <= n-1
设m[i][j]为计算A[i:j]的最小乘次,所以原问题的最优值为m[0][n-1]。
class Matrix:
def __init__(self, row_num=0, col_num=0, matrix=None):
if matrix != None:
self.row_num = len(matrix)
self.col_num = len(matrix[0])
else:
self.row_num = row_num
self.col_num = col_num
self.matrix = matrix
def matrix_chain(matrixs):
matrix_num = len(matrixs)
count = [[0 for j in range(matrix_num)] for i in range(matrix_num)]
flag = [[0 for j in range(matrix_num)] for i in range(matrix_num)]
for interval in range(1, matrix_num + 1):
for i in range(matrix_num - interval):
j = i + interval
count[i][j] = count[i][i] + count[i + 1][j] + matrixs[i].row_num * matrixs[i + 1].row_num * matrixs[j].col_num
flag[i][j] = i
for k in range(i + 1, j):
temp = count[i][k] + count[k + 1][j] + matrixs[i].row_num * matrixs[k + 1].row_num * matrixs[j].col_num
if temp < count[i][j]:
count[i][j] = temp
flag[i][j] = k
traceback(0, matrix_num - 1, flag)
return count[0][matrix_num - 1]
def traceback(i, j, flag):
if i == j:
return
if j - i > 1:
print(str(i + 1) + '~' + str(j + 1), end=': ')
print(str(i + 1) + ":" + str(flag[i][j] + 1), end=',')
print(str(flag[i][j] + 2) + ":" + str(j + 1))
traceback(i, flag[i][j], flag)
traceback(flag[i][j] + 1, j, flag)
def main():
matrixs = [Matrix(30, 35), Matrix(35, 15), Matrix(15, 5), Matrix(5, 10), Matrix(10, 20), Matrix(20, 25)]
result = matrix_chain(matrixs)
print(result)
if __name__ == '__main__':
main()
运行结果为:
1~6: 1:3,4:6
1~3: 1:1,2:3
4~6: 4:5,6:6
15125
表示计算顺序为 ( ( A 1 ( A 2 A 3 ) ) ( ( A 4 A 5 ) A 6 ) ) ((A1(A2A3))((A4A5)A6)) ((A1(A2A3))((A4A5)A6))