您的位置:首页 > 其它

shu_p55 矩阵连乘问题

2013-11-18 15:57 260 查看
http://acmoj.shu.edu.cn/openjudge-edu/viewproblem.php?coll_id=1&prob_id=55

分析:

     1.对于A[1:n]的最次序所包含的计算矩阵子链A[1:k]和A[k+1:n]的次序也是最优的,即具有最优子结构。所以假设对于A[i:j](1<=i<=j<=n),所需最少数乘次数为m[i][j],则原问题的最优值为m[1]
。动态方程如下:

        m[i][j]=0                                                 i=j

        m[i][j]=Min{m[i][k]+m[k+1][j]+P[i-1]*P[k]*P[j]}   i<j (i<=k<j)

     2.输出括号

       本题不仅要求输出m[i][j],同时还应在输出结果中用括号来显示计算的顺序。为此在动态规划算中加入了s[][]数组,用来记录最优的断开位置。然后利用Traceback算法输出最优计算次序。由于输出样例中的最外层没有加括号,所以在Traceback函数中需要进行判断,与一般情况分开讨论。

代码:

//shuoj P55 MatrixChain
#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define Max 24

int N;
int m[Max][Max],p[Max],s[Max][Max];
void Traceback(int i,int j)
{
if(i==j) {cout<<"A"<<i;return;}
if(i==1&&j==N){
Traceback(i,s[i][j]);
Traceback(s[i][j]+1,j);

}
else {
cout<<"(";
Traceback(i,s[i][j]);
Traceback(s[i][j]+1,j);
cout<<")";
}
}

int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);

int t=1;
while(scanf("%d",&N)!=EOF){
for(int i=0;i<=N;i++) cin>>p[i];
for(int i=0;i<=N;i++) m[i][i]=0;
if(N==1){
cout<<"Case "<<t++<<endl
<<"0"<<' '<<"A1"<<endl;
continue;
}
if(N==2){
cout<<"Case "<<t++<<endl
<<(p[0]*p[1]*p[2])<<' '<<"A1A2"<<endl;
continue;
}
for(int r=2;r<=N;r++)
for(int i=1;i<=N-r+1;i++){
int j=i+r-1;
m[i][j]=m[i+1][j]+p[i-1]*p[i]*p[j];
s[i][j]=i;
for(int k=i+1;k<j;k++){
int 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;
}
}
}
cout<<"Case "<<t++<<endl;
cout<<m[1]
<<' ';
Traceback(1,N);
cout<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  dp