如果对动态规划概念不懂的同学请看这里动态规划原理
矩阵连乘积问题
m X n矩阵A与n X p矩阵B相乘需耗费的时间。
我们把mnp作为两个矩阵相乘所需时间的测量值。
现在假设三个矩阵A、B和C的乘积,有两种方式计算此乘积,那么有(AB)C和A(BC)两种方式计算此乘积。尽管两种不同的计算顺序所得的结果是相同的,但时间消耗会有很大差距。
矩阵连乘积问题定义:
给定n个矩阵{A1,A2,A3,……,An},其中Ai与Ai+1是可乘的,i=1,2,……n-1。考察这n个矩阵的连乘积A1A2A3……An。
- 由于矩阵乘法满足结合律,所以计算矩阵的连乘积可以有许多不同的计算次序。
- 这种次序可以加括号的方式来确定。
- 若一个矩阵连乘积的计算机次序完全确定,也就是说该连乘积已完全加括号,则可反复调用2个矩阵相乘的标准算法来计算出矩阵连乘积
以四矩阵个为例
第一步:分析最优解的结构 - 将矩阵连乘积AiAi+1…Aj简记为A[i:j],这里i<=j;
- 考察计算A[1:n]的最优计算次序。
- 设这个计算次序在矩阵Ak和Ak+1之间将矩阵链断开,1<=K<n,则其相应完全加括号方式为(A1A2…Ak)(Ak+1Ak+2…An)
- 计算量:A[1:k]的计算量加上A[k+1:n] 的计算量,再加上A[1:k]和A[k+1:n]相乘的计算量
第二步:建立递归关系
- 设计算A[i:j],1<=i<=j<=n,所需要的最少数乘次数m[i,j],则原问题的最优值为m[1,n];
- 当i=j时,A[i:j]=Ai,因此,m[i,i]=0,i=1,2,3…,n
- 当i<j时,m[i,j]=m[i,k]+m[K+1,j]+pi-1pkpj
- 这里Ai的维数是pi-1Xpi可以递归定义为:
计算最优解
#define NUM 51;
int p[NUM];
int m[NUM][NUM];
int s[NUM][NUM];
void MatrixChain(int n)
{
for(int i=1;i<=n;i++) m[i][i]=0;
for(int r=2;r<=n;r++)//列
for(int l=1;l<=n-r+1;l++)//行
{
int j=l+r-1;
int i=l;//初值从i开始断开
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;}
}
}
}
构造最优解
s[i][j]已经存储了构造最优解足够的信息
void TraceBook(int i,int j)
{
if(i==j) printf("A%d",i);
else{
printf("(");
TraceBack(i,s[i][j]);
TraceBack(s[i][j]+1,j);
printf(")");
}
}
时间复杂度
三重O(n)循环,工作量W(n)=O(n3)
备忘录也是三重O(n)循环,工作量W(n)=O(n3)
最后追踪解工作量O(n)