矩阵连乘
知识标签:DP,algorithm
推导公式
d[i][j] d [ i ] [ j ] :从矩阵i到矩阵j连乘所需乘法次数最少值
pk p k :对于第k个矩阵 20×10 20 × 10 , pk p k 表示 10 10 , pk−1 p k − 1 表示 20 20
- 分析此公式可知当 i>j i > j 时无意义,即全部 d[i][j] d [ i ] [ j ] 值构成的矩阵为三角矩阵
- 从 d[i,j] d [ i , j ] 开始,其中 i=1,j=i+1 i = 1 , j = i + 1 ,即先求 (1,2),(2,3),(3,4)... ( 1 , 2 ) , ( 2 , 3 ) , ( 3 , 4 ) . . . 这个斜对角线的 d[i][j] d [ i ] [ j ]
- 然后向下循环, i=1,j=i+2 i = 1 , j = i + 2 ,即求 (1,3),(2,4)(3,5)... ( 1 , 3 ) , ( 2 , 4 ) ( 3 , 5 ) . . . 这个斜对角线的 d[i][j] d [ i ] [ j ]
- 然后继续下去,直到把 (1,t) ( 1 , t ) 求完,其中 t t 表示矩阵个数
code
代码中m数组中存放的值
#include<iostream>
#include<string.h>
#define MAX 2100000000
#define SIZE 100
int d[SIZE][SIZE];
int m[SIZE];
int matrix_DP(int n)
{
int sum;
memset(d, 0, sizeof(d));
//每循环一次计算一条斜对角线
for(int len = 2; len < n; ++len)
{//第一次循环计算斜对角线(1,2),(2,3),(3,4)...
for(int i = 1, j = len; j < n; ++i, ++j)
{
int min = MAX;
//k在[i,j)范围内
for(int k = i; k != j; ++k)
{
sum = d[i][k] + d[k + 1][j] + m[i - 1] * m[k] * m[j];
if(sum < min)
{
min = sum;
}
}
d[i][j] = min;
}
}
//返回从第一个矩阵到最后一个矩阵的最少乘法次数
return d[1][n - 1];
}
int main(void)
{
int len = -1;
while(std::cin >> m[++len]);
//len为数组m的长度
std::cout << "len : "<< len << std::endl;
std::cout << "matrix_DP return :" << matrix_DP(len) << std::endl;
//输出d[i][j]
for(int i = 1; i < len; ++i)
{
std::cout << std::endl;
for(int j = 1; j < len; ++j)
{
std::cout << d[i][j] << '\t' << std::flush;
}
std::cout << std::endl;
}
return 0;
}