计算A[i:j],1<=i<=j<=n,所需的最小乘法次数为m[i][j],则所求最优解为m[1][n]

当i==j时,A[i:j]为单一矩阵,无需计算,所以m[i][i]=0,i=1,2,3……,n;

当i<j时,可利用最优解计算m[i][j]。事实上,若计算A[i:j]的最优次序在Ak和Ak+1之间断开,i<=k<j,则

m[i][j]=m[i][k]+m[k+1][j]+pi-1*pk*pj.由于计算时并不知道k的位置,不过k只有k-j个可能,k=i,i+1,……,j-1.

因此,k是这j-i个位置中使计算量大刀最下的那个位置,从而m[i][j]可以递归定义为

m[i][j]给出了最优解,即计算A[i:j]所需的最少数乘次数。同时还确定了A[i:j]的最优次序的断开位置k,也就是说,对于这个k有

m[i][j]=m[i][k]+m[k+1][j]+pi-1*pk*pj

若将对应于m[i][j]的断开位置标记为s[i][j],在计算出最优值后,可由递归地由s[i][j]构造出最优解

View Code
#include<iostream>
#include<cstring>
using namespace std;

#define N 110

int m[N][N];
int s[N][N];

void MatrixChain(int *p,int n)
{
int i,r,j,k,t;
for(i=1;i<=n;i++)
m[i][i]=0;
for(r=2;r<=n;r++)//r为矩阵链长度
{
for(i=1;i<=n-r+1;i++)
{
j=i+r-1;
m[i][j]=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 Traceback(int i,int j)
{
if(i==j)
return ;
Traceback(i,s[i][j]);
Traceback(s[i][j]+1,j);
cout<<"Multiply A"<<i<<","<<s[i][j];
cout<<"and A"<<(s[i][j]+1)<<","<<j<<endl;
}

int main()
{
int T,i,n,p[N];
cin>>T;
while(T--)
{
cin>>n;
for(i=0;i<=n;i++)
cin>>p[i];
memset(m,0,sizeof(m));
memset(s,0,sizeof(s));
MatrixChain(p,n);
cout<<m[1][n]<<endl;
Traceback(1,n);
}
return 0;
}

备忘录法:

View Code
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;
}
}
m[i][j]=u;
return u;
}




 

posted on 2012-03-25 13:35  pcoda  阅读(375)  评论(0编辑  收藏  举报