矩陣連乘也是常見的動態規劃例子之一。形式如下:給出N個矩陣,矩陣是有序的,即相鄰矩陣之間可以進行乘法運算,求這些矩陣最小的相乘次數。如:矩陣30*15、15*5、5*10,先讓前兩個矩陣進行相乘時、再和最後一個矩陣相乘時,乘法計算次數爲30*15*5+30*5*10=3750,;先讓後兩個矩陣相乘、再和第一個矩陣相乘時,乘法計算次數爲15*5*10+30*15*10=5250。由此可見,不同的運算順序,會影響到乘法的計算次數。
首先假設以下變量:
n表示矩陣的個數
Ai表示第i個矩陣
A[i:j]表示矩陣連乘AiA{i+1}..Aj
pi表示Ai的列數
p{i-1}表示Ai的行數
k表示矩陣連乘斷開的位置爲k,表示在Ak和A{k+1}之間斷開
m[i,j]表示A[i:j]的最少乘次,m[1,n]即問題的最優解
假設k是對矩陣鏈A[i:j]一分爲二得到最優解時的斷開位置,則m[i,k]和m[k+1,j]分別是兩個子矩陣鏈A[i,k]和A[k+1,j]的最優解。兩個矩陣最後要相乘才能得到A[i,j],因此,最後要加上p{i-1}*pk*pj,也就是兩子矩陣相乘的數乘次數,才能得到總的數乘次數。公式如下:
Java代碼如下:
int arr[ ] = {30,15,5,10};
int minMultiplication = 0;
final int LENGTH = arr.length;
int[ ][ ] s = new int [ LENGTH ][ LENGTH ];
int[ ][ ] m = new int [ LENGTH ][ LENGTH ];
for(int i=0;i<LENGTH;i++)
{
for(int j=0;j<LENGTH;j++){
s[ i ][ j ] = 0;
m[ i ][ j ] = 0;
}
}
for(int r=2; r<=LENGTH-1; r++) //r爲當前計算的鏈長(子問題規模)
{
for(int i=1; i<=LENGTH-1-r+1; i++)//LENGTH-1-r+1爲最後一個r鏈的前邊界
{
int j = i+r-1;//計算前邊界爲r,鏈長爲r的鏈的後邊界
m[ i ][ j ] = m[ i+1 ][ j ] + arr[ i-1 ]*arr[ i ]*arr[ j ];//將鏈ij劃分爲A(i) * ( A[i+1:j] )
s[ i ][ j ] = i; //s[ ][ ]存儲各子問題的決策
for(int k=i+1; k<j; k++) //將鏈ij劃分爲( A[i:k] )* (A[k+1:j])
{
int tmp = m[ i ][ k ] + m[ k+1 ][ j ] + arr[ i-1 ]*arr[ k ]*arr[ j ];
if(tmp<m[ i ][ j ])
{
m[ i ][ j ] = tmp;
s[ i ][ j ] = k;
}
}
}
}
minMultiplication = m[1][LENGTH-1];
System.out.println(minMultiplication);