一、矩阵连乘问题
1.两个矩阵乘积所需的计算量
void matrixMultiply(int **a, int **b, int **c, int ra, int ca, int rb, int cb)
{
if(ca!=rb) return;
for(int i=0; i<ra; ++i)
for(int j=0; j<cb; ++j)
{
int sum = a[i][0] * b[0][j];
for(int k=1; k<ca;++k)
sum += a[i][k] * a[k][j];
c[i][j] = sum;
}
}
可见需三重循环,总共要ra*ca*cb次数乘。
2.矩阵连乘时,加括号方式影响整个计算量。A1A2A3(10×100, 100×5, 5×50),如(A1A2)A3需要7500次,而A1(A2A3)需要75000次,两者相差10倍。矩阵连乘问题就是求A1A2...An个矩阵的计算次序使得所需计算量最少,其中矩阵的行列存储在数据p中,A1为p0×p1,A2为p1×p2。
3.分析
设计算A[i:j],1≤i≤j≤n,所需的最少数乘次数为m[i][j],则显然原问题的最少数乘次为m[1][n]。
若计算Ai...Aj时在Ak和Ak+1之间断开,则m[i][j]=m[i][k]+m[k+1][j]+pi-1pkpj。因为如果要想整个计算量最少,则Ai...Ak和Ak+1...Aj的计算量也必须最少。只要确定的k的位置,则就找到了一个断点。k只有i, i+1,...,j-1这几种可能。m[i][j]可递归地定义为:
。
4.利用递归直接计算a[i][j]。(其中s[i][j]保存的是断开点)
int RecurMatrixCahin(int i, int j)
{
if(i == j) return 0;
int u = RecurMatrixCahin(i,i)+RecurMatrixCahin(i+1,j)+p[i-1]*p[i]*p[j];
s[i][j] = i;
for(int k=i+1; k<j;++k)
{
int t = RecurMatrixCahin(i,k)+RecurMatrixCahin(k+1,j)+p[i-1]*p[k]*p[j];
if(t < u)
{
u = t;
s[i][j] = k;
}
}
return u;
}
问题是:太多的子问题被重复计算。效率太低。2n。
5.动态规划方法
A1
|
A2
|
A3
|
A4
|
A5
|
A6
|
30
´
35
|
35
´
15
|
15
´
5
|
5
´
10
|
10
´
20
|
20
´
25
|
{
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j) m[i][j]=0;
return LookupChain(1, n);
}
int LookupChain(int i, int j)
{
if(m[i][j]>0) return m[i][j];
if(i==j) return 0;
int u = LookupChain(i,i)+LookupChain(i+1,j)+p[i-1]*p[i]*p[j];
s[i][j] = i;
for(int k=i+1; k<j;++k)
{
int t = LookupChain(i,k)+LookupChain(k+1,j)+p[i-1]*p[k]*p[j];
if(t < u)
{
u = t;
s[i][j] = k;
}
}
return u;
}
}
以上内容摘自《计算机算法设计与分析》王晓东。