动态规划——矩阵连乘
设第i个矩阵为Ai,将矩阵连乘积AiAi+1…Aj记为A[i:j].
求A[1:n]最少计算次序.
采用完全加括号,即在不同位置将矩阵连乘分割,比较分割后最优,求出最优值。分割位置k(1<=k<n)。
#include <iostream>
using namespace std;
//p存储 行列数,n=矩阵个数,m存矩阵最少乘次数(最优值),n存断开位置(最优解)
void MatrixChain( int *p, int n, int m[][100], int s[][100] ) {
for( int i = 1; i <= n; i++ ) {
m[i][i] = 0; //对角线赋值为0,因为对角线表示单一矩阵,无最少乘次数
s[i][i] = 0; //同理,无断开位置
}
for( int r = 2; r <= n; r++ ) { //r控制连乘时矩阵个数,r=2表示求两个矩阵最少乘
for( int i = 1; i <= n - r + 1; i++ ) { //i表示开始矩阵位置
int j = i + r - 1; //连乘矩阵结束位置
m[i][j] = m[i][i] + m[i + 1][j] + p[i - 1] * p[i] * p[j]; //断开位置在初始位置时的m
//m[2][5]意思是 第2个矩阵到第5个矩阵(共4个矩阵)的连乘最少次数
//同理 s[2][5]意思是 第2个矩阵到第5个矩阵(共4个矩阵)的最少断点
s[i][j] = i;
for( int k = i + 1; k < j; k++ ) { //断开位置 i<=k<j
//切换断点,更新连乘最少次数
int temp = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if( m[i][j] > temp ) {
m[i][j] = temp;
s[i][j] = k;
}
}
}
}
}
void TraceBack( int i, int j, int s[][100] ) {
if( i == j ) {
return ;
}
TraceBack( i, s[i][j], s );
TraceBack( s[i][j] + 1, j, s );
cout << s[i][j] << "," << s[i][j] + 1;
}
int main() {
int p[100];
int n;
int m[100][100];
int s[100][100];
int count = 0;
cin >> n;
for( int i = 1; i <= n; i++ ) {
cin >> p[count++];
cin >> p[count];
}
MatrixChain( p, n, m, s );
for( int i = 0; i <= n; i++ ) {
for( int j = 0; j <= n; j++ ) {
if( m[i][j] < 0 ) {
printf( "\t-1" );
} else {
printf( "\t%2d", m[i][j] );
}
}
cout << endl;
}
system( "pause" );
return 0;
}