题目:
给定n个矩阵{A1,A2,……,An},其中Ai与Ai+1是可乘的,i=1,2,……,n-1.考察这n个矩阵的连乘积A1A2……An,找出计算量最小的计算次序。
算法描述
1 递归
对于每一个i,j区间,有一个变量k表示从第k个数组划分,k的范围是[i,j-1],枚举一个区间的所有划分情况然后求最小值,这两个子情况我们还不知道,所以就要再次递归,求解每一种子情况的答案~:
(1)设一个r(“无限大”)让每个求得的值与它比较
(2)先求一个值,让之后每个求得的值与第一个值比较
2动态规划
自底向上
(1) 先初始化m[i][i]
(2) 依次从链长为[2:n]递增分别计算不同链长的矩阵连乘最优值。
(3) 先令m[i][j]最优值为矩阵链首元素划分下的值,后再进行对比。
(4) 计算k∈[i+1:j-1]递增划分下最优值,并和之前已保存的最优值对比,取小者。
3备忘录
自顶向下的方法又叫备忘录,也就是说,在递归的基础上,我们开个数组存值,当需要的值已经求得,直接返回,不用再重复计算了
递归
#include <stdio.h>
#include <stdlib.h>
int M(int i,int j,int p[6],int s[][7])
{
if(i==j) 0;
int r=10000000000;
int temp,k;
for(k=i;k<j;k++)
{
temp=M(i,k,p,s)+M(k+1,j,p,s)+p[i-1]*p[k]*p[j];
if(temp<r)
{
r=temp;
s[i][j]=k;
}
}
return r;
}
void ConstructSolution(int i, int j, int s[][7])
{
if (i == j)
printf("A%d",i);
else
{
printf("(");
ConstructSolution(i,s[i][j],s);
ConstructSolution(s[i][j]+1,j,s);
printf(")");
}
}
int main()
{
int n=6;
int p[]={30,35,15,5,10,20,25};
int s[7][7]={0};
int m[7][7]={0};
M(1,n,p,s);
ConstructSolution(1,n,s);
}
动态规划
#include <stdio.h>
#include <stdlib.h>
void MatrixChain(int p[6],int n,int m[][7],int s[][7])
{
int r=0,i=0,j=0,k=0,t=0;
for(i=1;i<=n;i++)
m[i][i]==0;
for(r=2;r<=n;r++)
for(i=1;i<=n-r+1;i++)//n-r+1表示保证有r个矩阵相乘
{
j=i+r-1;//当r=3时 有三个矩阵 但j=i+2,所以需要-1
m[i][j]=m[i][i]+m[i+1][j]+p[i-1]*p[i]*p[j];//默认在初始下标之后断开,得到初始值
s[i][j]=i;
for(k=i+1;k<j;k++)
{
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 TrackBack(int i,int j, int s[][7])
{
if(i==j) return;
TrackBack(i,s[i][j],s);//递归第一次断开之前
TrackBack(s[i][j]+1,j,s);
printf("A%d",i);
printf(" and A%d",j);
printf("\n");
}
int main()
{
int n=6;
int p[]={30,35,15,5,10,20,25};
int s[7][7]={0};
int m[7][7]={0};
MatrixChain(p,n,m,s);
TrackBack(1,n,s);
}
`备忘录
#include <stdio.h>
#include <stdlib.h>
int MemorizedMatrixChain(int n,int p[6],int m[7][7],int s[7][7])
{
int i,j;
for(i=0;j<=n;i++)
for(j=i;j<=n;j++)
m[i][j]=0;
return LookupChain(1,n,p,m,s);
}
int LookupChain(int i,int j,int p[6],int m[][7],int s[][7])
{
int k;
if(i==j) return m[i][j]=0;
if(m[i][j]>0) return m[i][j];
int u=LookupChain(i,i,p,m,s)+LookupChain(i+1,j,p,m,s)+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(k=i+1;k<j;k++){
int t=LookupChain(i,k,p,m,s)+LookupChain(k+1,j,p,m,s)+p[i-1]*p[k]*p[j];
if(t<u){u=t;s[i][j]=k;}}
m[i][j]=u;
return m[i][j];
}
void ConstructSolution(int i, int j, int s[][7])
{
if (i == j)
printf("A%d",i);
else
{
printf("(");
ConstructSolution(i,s[i][j],s);
ConstructSolution(s[i][j]+1,j,s);
printf(")");
}
}
int main()
{ int n=6;
int p[]={30,35,15,5,10,20,25};
int s[7][7]={0};
int m[7][7]={0};
MemorizedMatrixChain(n,p,m,s);
ConstructSolution(1,n,s);
}