矩阵连乘问题就是找到合适的位置使得就算量最小。设计算A[i:j],1<=i<=j<=n,所需的最少次数为m[i][j],则原问题的最优值为m[1][n].
当i=j时。A[i:j]=A[i]。为单一矩阵,不需要计算,因此m[i][i]=0;
当i<j时,m[i][j]=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j].(i<=k<j注意这里的k的取值,k将两个矩阵相乘为一个矩阵k前面的为一个包括k。k后面的为一个不包括一个。)
当i=j时。A[i:j]=A[i]。为单一矩阵,不需要计算,因此m[i][i]=0;
当i<j时,m[i][j]=m[i][k]+m[k+1][j]+p[i-1]*p[k]*p[j].(i<=k<j注意这里的k的取值,k将两个矩阵相乘为一个矩阵k前面的为一个包括k。k后面的为一个不包括一个。)
从而,m[i][j]可以递归的定义为:
代码如下:
#include<iostream>
#include<stdio.h>
using namespace std;
int weight[100+10][100+10];//记录从1..n相乘需要的计算量
int root[100+10][100+10];//记录在计算1...n的矩阵时,从哪里分开
int p[100+10];.//记录每个矩阵的列数
void init(int n)//初始化
{
for(int i=0;i<=n;i++)
{
cin>>p[i];
}
}
void matrixchain(int n)//计算矩阵的计算量并且记录分割点
{
for(int i=0;i<=n;i++)
{
weight[i][i]=0;
}
for(int r=1;r<=n;r++)
{
for(int i=1;i<=n-r;i++)
{
int j=i+r;
weight[i][j]=weight[i][j-1]+p[i-1]*p[j-1]*p[j];
root[i][j]=j-1;
for(int k=i;k<j;k++)
{
int t=weight[i][k]+weight[k+1][j]+p[i-1]*p[k]*p[j];
if(t<weight[i][j])
{
weight[i][j]=t;
root[i][j]=k;
}
}
}
}
}
void traceback(int i,int j)//输出分割
{
if(i>=j)return ;
traceback(i,root[i][j]);
traceback(root[i][j]+1,j);
cout<<"Multiply A"<<i<<","<<root[i][j];
cout<<"and A"<<(root[i][j]+1)<<","<<j<<endl;
}
int main()
{
int n;
while(cin>>n)
{
init(n);
matrixchain(n);
traceback(1,n);
cout<<endl<<endl<<endl<<endl;
}
return 0;
}