1274 奇怪的梦

 
描述

上完算法课回来的路上,你仍然为DP的优美而赞叹不已。

正所谓日有所思,夜有所梦,午觉也不例外。因为研究DP太过投入,睡午觉的时候你做了一个很奇怪的梦。

梦里你回到了19世纪。那时的人们还没有计算机的概念。而很不幸的,在时空旅行中你带上了你的笔记本。所以很自然的,你成为了那个年代最伟大的科学家之一。

这天,你和一群科学家同伴聚会。会上讨论了矩阵链乘法问题。当时还没有很好的解决方法。而你想到了刚刚算法课上讲到的动态规划方法(为什么是刚刚??应该是很久以后......)。

PS:有关矩阵链乘法问题参考算法导论第十五章第2节。

输入

第一行只有一个整数n,表示矩阵链的数目。
每条矩阵链描述如下:
第一行是一个整数m(0 < m <= 100)。表示一共有m个矩阵
接下来的m行每行一对整数Pi,Qi(0< Pi,Qi <=100)。表示矩阵Ai的维数。
输入数据保证矩阵相容。

输出

每条矩阵链输出两行。
第一行一个整数,表示最小的标量乘法次数。
第二行用加括号的方式描述此方法

当最优解不唯一时,按先左后右的顺序相乘。
例如有3个矩阵A1,A2,A3。当((A1A2)A3)和(A1(A2A3))相等时,输出((A1A2)A3)。

样例输入
1
6
30 35
35 15
15 5
5 10
10 20
20 25
样例输出
15125
((A1(A2A3))((A4A5)A6))

 

 

算法导论,动态规划

#include<iostream>
using namespace std;
void comeon(int a[110][110],int l,int r)
{
	if(l==r)cout<<"A"<<l+1;
	else if(l==r-1)cout<<"(A"<<l+1<<"A"<<r+1<<")";
	else 
	{
		cout<<"(";
		comeon(a,l,a[l][r]);
		comeon(a,a[l][r]+1,r);
		cout<<")";
	}
}
int main()
{
	int t,n,i,j,k,m,a[1100][2],d[110][110],hai[110][110]={0};
	cin>>t;
	while(t)
	{
		cin>>n;
		for(i=0;i<n;i++)cin>>a[i][0]>>a[i][1];
		for(i=0;i<n;i++)d[i][i]=0;
		for(k=1;k<n;k++)
			for(i=0;i<n-k;i++)
			{
				d[i][i+k]=d[i][i]+a[i][0]*a[i][1]*a[i+k][1]+d[i+1][i+k];
				hai[i][i+k]=i;
				for(j=i+1;j<i+k;j++)
				{
					m=d[i][j]+a[i][0]*a[j][1]*a[i+k][1]+d[j+1][i+k];
					if(d[i][i+k]>=m)
					{
						d[i][i+k]=m;
						hai[i][i+k]=j;
					}
				}
			}
			cout<<d[0][n-1]<<endl;
			comeon(hai,0,n-1);
			cout<<endl;
			//for(i=0;i<n;i++)
			//{
				//for(j=0;j<n;j++)cout<<hai[i][j]<<" ";
				//cout<<endl;
			//}
			t--;
	}
	return 0;
}


 

你可能感兴趣的:(1274 奇怪的梦)