问题描述:
给定n个矩阵的链
<A1,A2,...,An>
<script type="math/tex" id="MathJax-Element-700">
</script>,矩阵
Ai
的规模为
pi×pi+1(1≤i≤n)
,求完全括号化的方案,使得计算乘积
A1,A2,...,An
所需标量乘法的次数最少。
递推式:
m[i,j]={0,min{m[i,k]+m[k+1,j]+pipk+1pj+1},if i=j if i<j
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
const int N=6;
const int msize[6][2]={{30,35},{35,15},{15,5},{5,10},{10,20},{20,25}};
const int p[7]={30,35,15,5,10,20,25};//the size of matrix: eg. matrix[0]=30*35; matrix[i]=p[i]*p[i+1]
int m[N][N];//m[i][j]=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1]
vector< vector<int> > s(N);//store the split position
void matrix_chain_order(const int p[],int n)
{
n--;//the number of the matrixes
int i,j,l,k;
for(i=0;i<n;i++)
m[i][i]=0;
for(l=2;l<=n;l++){//l is the chain length, the maximum is n-1
for(i=0;i<=n-l;i++)//i is the start matrix of the chain,the last start matrix of the l length chain is n-l-1
{
j=i+l-1;//if the start of the chain is i,then the end of the chain is j, because j-i+1=l.
m[i][j]=INT_MAX;
for(k=i;k<j;k++)
{
int q=m[i][k]+m[k+1][j]+p[i]*p[k+1]*p[j+1];
if(q<m[i][j])
{
m[i][j]=q;
s[i][j]=k;
// cout<<k<<endl;
}
}
}
}
}
int look_up_chain(vector< vector<int> > &m,vector< vector<int> > &s,const int p[],int i,int j)
{
int k,q;
if(m[i][j]<INT_MAX)
return m[i][j];
if(i==j)
{
m[i][j]=0;
}else{
for(k=i;k<j;k++)
{
q=look_up_chain(m,s,p,i,k)+look_up_chain(m,s,p,k+1,j)+p[i]*p[k+1]*p[j+1];
if(q<m[i][j])
{
m[i][j]=q;
s[i][j]=k;
}
}
}
return m[i][j];
}
//带备忘机制的动态规划
int memorized_matrix_chain(const int p[],int n)
{
n--;//the total matrixes in the chain
vector< vector<int> > memo(n);
for(int i=0;i<n;i++)
memo[i].resize(n);
int i,j;
for(i=0;i<n;i++)
{
for(j=i;j<n;j++)
memo[i][j]=INT_MAX;
}
return look_up_chain(memo,s,p,0,n-1);
}
void print_optimal_parens(vector< vector<int> > & s,int i, int j)
{
if(i==j)
cout<<"A_"<<i+1;
else{
cout<<"(";
print_optimal_parens(s,i,s[i][j]);
print_optimal_parens(s,s[i][j]+1,j);
cout<<")";
}
}
int main(){
for(int i=0;i<N;i++)
s[i].resize(N);
// matrix_chain_order(p,N+1);
int ans=memorized_matrix_chain(p,N+1);
cout<<"the answer: "<<endl;
cout<<ans<<endl;
print_optimal_parens(s,0,N-1);
return 0;
}
用于实验的例子:
结果应为:
((A1(A2A3))((A4A5)A6))
运行过程:
运行结果: