问题描述:矩阵A和B可乘的条件是A的列数等于B的行数。若A是一个p×q矩阵,B是一个q×r矩阵,则其乘积C=AB是一个p×r矩阵。在计算矩阵乘积的标准算法中,主要计算量为p×q×r次数乘。
由于矩阵的乘法满足结合律,故计算矩阵的连乘积有许多不同的计算次序。
给定n个矩阵{ A1,A2,……,An },其中Ai和Ai+1是可乘的,i=1,2,……,n-1,求计算其连乘积A1×A2×……×An的最小乘法次数
输入格式:
第1行为一个正整数n,表示n个矩阵相乘,n≤100。
第2行为n+1个整数p0p1……pn,其中pi-1pi为矩阵Ai的行数和列数。
样例输入:
C++代码:
#include<iostream>
using namespace std;
#define MAX 100
int m[MAX][MAX];
int s[MAX][MAX];
void MatrixChain(int *p, int n)
{
for (int i = 1; i <= n; i++)
m[i][i] = 0;
for (int r = 2; r <= n; r++)
for (int i = 1; i <= n - r + 1; i++) {
int j = i + r - 1;
m[i][j] = m[i + 1][j] + p[i - 1] * p[i] * p[j];
s[i][j] = i;
for (int k = i + 1; k < j; k++) {
int t = m[i][k] + m[k + 1][j] + p[i - 1] * p[k] * p[j];
if (t < m[i][j]) { m[i][j] = t; s[i][j] = k; }
}
}
}
void traceback(int i, int j)
{
if (i == j)
cout << "A" << i;
else if (i == j - 1)
cout << "(A" << i << "A" << j << ")";
else
{
cout << "(";
traceback(i, s[i][j]);
traceback(s[i][j] + 1, j);
cout << ")";
}
}
int main()
{
int t;
int p[MAX + 1];//记录输入矩阵
cin >> t;//输入矩阵的数量
for (int i = 0; i <= t; i++)
cin >> p[i];
MatrixChain(p, t);
cout << m[1][t]<<endl;
system("PAUSE");
return 0;
}
解析:
解题的过程是求解矩阵连乘的最乘法次数,以及输出最优计算次序。
在这段代码,定义了MatrixChain函数和traceback函数,用于求解和输出最小乘法次数和最优计算次序。其中,MatrixChain函数使用动态规划的思想,根据所有可能的计算次序,计算出每种计算次序的乘法次数,从而得到最小乘法次数。而traceback函数则根据保存的信息,递归输出最优计算序。
具体地说,在MatrixChain函数中,首先初始化m数组为0,表示每个矩阵自身的乘法次数为0。然后使用两层循环来计算m和s数组的值。 外层循环变量r表示连乘的长度,从2到n(矩阵数量)。内层循环变量i表示起始位置,从1到n-r+1。每计算m[i][j]和s[i][j]的值,其中j=i-1。 通过一个内层循环变量k,遍历从i+1到j-1的所有中间位置,计算以k为分割点的连乘乘法次数t。如果t小于当前的m[i][j],更新m[i][j]和s[i][j]的值。 最终,输出m[1][t],即A1到At的连乘最小乘法次数。 在traceback函数中,根据保存在s数组中的分割点信息,递归地输出矩阵的乘法次序。如果i等于j,输出Ai;如果i等于j-1,输出(AiAj);否则,输出(Atraceback(i, s[i][j])traceback(s[i][j] + 1, j))。 最后,在main函数中输入矩阵数量和每个矩阵的尺寸信息,调用MatrixChain函数求解最小乘法次数输出结果。然后调用traceback函数输出最优计算次序。 希望以上解答对你有帮助!