# 算法之动态规划-矩阵链相乘（matrix-chain multiplication）

## Matrix-chain multiplication

### first step: Characterize the structure of an optimal solution

Aij$A_{i··j}$ 划分为 Aik$A_{i··k}$A(k+1)j$A_{(k+1)··j}$

### second step: Recursively define the value of an optimal solution

A3$A_3$ 的行下标为 p[2]=15$p[2]=15$ 列下标为p[3]=5$p[3]=5$

• i=j$i = j$ : Aij=Ai$A_{i··j} = A_i$，单个矩阵，所以M[i,j]=0$M[i,j]=0$

• i<j$i < j$ : Aij$A_{i··j}$可分为Aik$A_{i··k}$的矩阵乘规模数加上Ak+1Aj$A_{k+1}··A_j$的矩阵乘规模数，再加上两个分矩阵的相乘规模数
数学表达式为：M[i,j]=M[i,k]+M[k+1,j]+pi1pkpj$M[i,j] = M[i,k] + M[k+1,j] + p_{i-1}p_kp_j$
重点理解pi1pkpj$p_{i-1}p_kp_j$表达的意思：现在M[i,k]$M[i,k]$可理解为最终行下标为i，列下表为k的矩阵；M[k+1,j]$M[k+1,j]$可理解为最终行下标为k+1，列下表为j的矩阵;再把这两个矩阵相乘，也就是等同于两个矩阵相乘的规模数，再结合图一，得出结果——pi1pkpj$p_{i-1}p_kp_j$

### third step: Compute the value of an optimal solution

• 递归算法：
matrix(p,i,j) {
if i == j
m[i,j] = 0
retrun m[i,j]
m[i,j] = 999999999999
for k = i to j - 1
temp = matrix(p,i,k) + matrix(p,k+1,j) + p[i-1]p[k]p[j]
if temp < m[i,j]
m[i,j] = temp
return m[i,j]
}

- 动态规划:自顶向下

s[m,n]代表Am··n最优划分位置为s[m,n]，记录下最优划分的位置
memory-matrix(p) {
n = p.length - 1
let s[n,n] be a global array
let m[n,n] be a new array
for i = 1 to n
for j = i to n
m[i,j] = 999999999
return look-chain(m,p,1,n)
}

look-chain(m,p,i,j) {
if m[i,j] < 9999999999
return m[i,j]
if i == j
m[i,j] = 0
else for k = i to j - 1
q = look-chain(m,p,j,k) + matrix(m,p,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[i,j]
}

### At last：Construct an optimal solution from computed information

printPartition(s,i,j) {
if i == j
print "Ai"
else print "("
printPartition(s,i,s[i,j])
printPartition(s,s[i,j]+1,j)
print")"
}