大致题意为给定一个矩阵序列,求最小运算次数的次序。记忆化搜索,再根据dp结果查找路径即可,设状态dp(i,j)为第i个矩阵到第j个矩阵的最小运算次数,那么状态转移方程为dp(i,j)=min{dp(i,k)+dp(k+1,j)+r(i)*c(k)*c(j)},其中i<=k<j,r(i)为第i个矩阵的行数,c(i)为第i个矩阵的列数,那么一遍dp之后即可得到最小计算次数,路径的记录可以每到达一个区间,就将区间括起来,根据之前的计算,找到最小划分,递归进去即可。
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
int r[11],c[11],pre[11]={0},post[11]={0};
int ans[11][11];
int dp(int i,int j)
{
if(ans[i][j]!=0x7FFFFFFF) return ans[i][j];
for(int k=i;k<j;k++){
ans[i][j]=min(ans[i][j],dp(i,k)+dp(k+1,j)+r[i]*c[k]*c[j]);
}
return ans[i][j];
}
void gp(int i,int j)
{
if(i==j) return ;
pre[i]++;post[j]++;
int p,k;
for(k=i;k<j;k++){
if((ans[i][k]+ans[k+1][j]+r[i]*c[k]*c[j])==ans[i][j])
p=k;
}
gp(i,p);gp(p+1,j);
}
int main()
{
int n,ca=1;
while(cin>>n&&n){
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++) ans[i][j]=0x7FFFFFFF;
for(int i=1;i<=n;i++) {cin>>r[i]>>c[i];pre[i]=post[i]=0;ans[i][i]=0;}
dp(1,n);
gp(1,n);
cout<<"Case "<<ca++<<": ";
for(int i=1;i<=n;i++){
for(int j=1;j<=pre[i];j++) cout<<'(';
cout<<'A'<<i;
for(int j=1;j<=post[i];j++) cout<<')';
if(i!=n) cout<<" x ";
}
cout<<endl;
}
return 0;
}