一、问题
设A1,A2……An为n个矩阵的序列,其中Ai为Pi-1*Pi阶矩阵
这个矩阵的输入链用向量P<P0,P1,……Pn>表示。给定向量P确定一种乘法次序,使得基本运算的总次数达到最小。
例如P<10,100,5,50>,则A1:10×100 A2:100×5 A3:5×50
- (A1A2)A3=10×100×5+10×5×50=7500
2)A1(A2A3)=10×100×50+100×5×50=75000
二、问题分析
(1)蛮力法:
枚举所有可能的乘法次序针对每种次序计算基本运算次数,找出具有最小运算次数的乘法次序,每一种乘法次序代表了在n个项中加n-1个括号。
(2)动态规划法:
Ai-j:表示矩阵链相乘的子问题Ai,Ai+1,……Aj;
m[i……j]:表示得到乘积Ai……j所用的最小基本运算次数
假定最后一次相乘发生在矩阵链Ai……k和Ak+1……j之间即
A1A2……Aj=(A1A2……Ak)(Ak+1,……Aj),k=i,i+1……j-1
m[i,j]
(1) 0 i=j
(2)RecurMatrixChain(P,i,k)+RecurMatrixChain(P,k+1,j)+Pi-1PkPj i<j
三、代码·设计
void min_multi_martix(int P[], int n)
{
int dp[MAXN][MAXN];
memset(dp, inf, sizeof(dp));
if (n >= 2)
for (int i = 1; i <= n - 1; i++)
{
dp[i][i + 1] = P[i] * P[i + 1] * P[i + 2];
dp[i][i] = 0;
}
for (int len = 3; len <= n; len++)
for (int i = 1; i <= n - len + 1; i++)
{
int j = i + len - 1;
for (int k = i; k < j; k++)
if (dp[i][j] > dp[i][k] + dp[k + 1][j] + P[i] * P[k + 1] * P[j + 1])
{
dp[i][j] = dp[i][k] + dp[k + 1][j] + P[i] * P[k + 1] * P[j + 1];
s[i][j] = k;
}
}
printf("矩阵链最少乘法次数?%d\n", dp[1][n]);
printf("分割点");
find_div(1, n);
}
四、时间复杂度
T=O(n^3);
五、代码地址
https://github.com/yttb/hello-world