矩阵乘法次数优化
矩阵乘法次数优化
对于n个矩阵相乘并且矩阵的规模很大所以优化结合路相当重要的事件,由于矩阵的乘法只有结合律而没有交换律的特点,所以对于矩阵来说不同的结合律产生不同的乘法次数,不同的乘法次数又会影响着计算机的运行效率
矩阵乘法满足的条件
- 两个矩阵相乘形如 Amj与Ajn
- 两个矩阵相乘的次数 m*j*n
对于两个矩阵相乘必须满足 Ai*Ak Ak*Aj 即形如 n*m m*i 的矩阵才能进行乘法运算
而对于矩阵的乘法运算是相乘再相加,所以执行的乘法次数就是 Ai*Ak*Aj
如何求解
采用动态规划,自底向上的顺序求解
- 对于n个矩阵相乘,我们可以将矩阵拆分成两部分
- 每部分最小的乘法次数相加之后再将新的矩阵乘法次数相加处理得到最终的结果
- 我们假设将k作为划分括号的依据(即将n个矩阵划分成两部分以第k个为划分基础)
- 所以对于 n个矩阵的相乘的最小次数转化为两部分
第一部分:第1个矩阵到第k个矩阵的最小次数 即min(matrix[1][k])
第二部分: 第k+1个矩阵到第n个矩阵 即min(matrix[k+1][n])
处理新矩阵: 然后计算这两部分新构成的矩阵需要的乘法次数 d[0]*d[k]*d[n]- 所以动态方程为 matrix[1][n] = matrix[1][k] + matrix[k+1][n] + d[0]*d[k]*d[n];
推广对于 第i个到第j个矩阵的乘法次数 matrix[i][j] = matrix[i][k]+matrix[k+1][j] + d[i-1]*d[k]*d[j];
#include<iostream>
using namespace std;
#define maxn 1000
int d[maxn+5];
int dd[maxn+5][maxn+5];//矩阵规模
int main()
{
int n;//矩阵的个数
cin >> n;
for (int i = 0; i <= n; i++)
{
cin >> d[i];//矩阵的结构 n+1个下标
}
int start, end;
cin >> start >> end;//矩阵的起始与终点
for (int i = 1; i <= n; i++)
{
dd[i][i] = 0;//自身无需进行乘法
}
int cur;
for (int r = 2; r <= n; r++)
{
for (int i =1 ; i <= n-r+1 ; i++)
{
int j = i + r - 1;
dd[i][j] = dd[i + 1][j] + d[i - 1] * d[i] * d[j];
for (int k = i; k < j; k++)// 当求矩阵位于i - j 区间 k 为区间变动数字
{
cur = dd[i][k] + dd[k + 1][j] + d[i - 1] * d[k] * d[j];
if (cur < dd[i][j])dd[i][j] = cur;
}
}
}
cout <<"矩阵【"<<start<<","<<end<<"】最小乘法次数为: "<< dd[start][end] << endl;
return 0;
}
时间复杂度
O(n3)