题目地址:http://218.5.241.13:8060/oj/showProblem.jsp?pid=1104
想了想,还是把原题也贴上来吧,这个oj看起来跟我们学校原来那个看起来好像啊,我们学校那个破oj就稀里糊涂的不见了,万一那天这个也一样,岂不很纠结。。。
Description
在科学计算中经常要计算矩阵的乘积。矩阵A和B可乘的条件是矩阵A的列数等于矩阵B的行数。若A是一个p×q的矩阵,B是一个q×r的矩阵,则其乘积C=AB是一个p×r的矩阵。其标准计算公式为:
由该公式知计算C=AB总共需要pqr次的数乘。
为了说明在计算矩阵连乘积时加括号方式对整个计算量的影响,我们来看一个计算3个矩阵{A1,A2,A3}的连乘积的例子。设这3个矩阵的维数分别为10×100,100×5和5×50。若按第一种加括号方式((A1A2)A3)来计算,总共需要10×100×5+10×5×50=7500次的数乘。若按第二种加括号方式(A1(A2A3))来计算,则需要的数乘次数为100×5×50+10×100×50=75000。第二种加括号方式的计算量是第一种加括号方式的计算量的10倍。由此可见,在计算矩阵连乘积时,加括号方式,即计算次序对计算量有很大影响。
于是,人们自然会提出矩阵连乘积的最优计算次序问题,即对于给定的相继n个矩阵{A1,A2,…,An}(其中Ai的维数为pi-1×pi ,i=1,2,…,n),如何确定计算矩阵连乘积A1A2…An的一个计算次序(完全加括号方式),使得依此次序计算矩阵连乘积需要的数乘次数最少。
Input
Ouput
Sample Input
Sample Output
Source
zmh
《算法导论》和《算法竞赛入门经典》中都有讲到的一道题,纠结了一阵子完全看不懂,打算放弃,转看《算法艺术与信息学竞赛》上的“括号配对”,因为之前在nyoj上见过这道题,又是纠结了好久,终于按着书上的伪代码AC了,没想到再回头看这道题立刻就思路清晰了,递归穷举加记忆解决~
f(i,j)=min{ f(i,k)+f(k+1,j)+a[i][1]*a[k][2]*a[j][2] | k=i to j-1 }
学动规到现在没多长时间,只理解到目前统一解题思路大概就是 穷举,不过由于动规题目的特殊性,在穷举的过程中会有很多问题是重复的,也就是说动规其实是一种可以省下很多时间的穷举法,至于省时间的方式知道两种:自底向上递推;自顶向下递归并记录,每次求解前先查记录。
代码备份:
#include <cstdio>
#include<cstring>
int s[1005][1005],a[1005][3];
int f(int i,int j)
{
if(i==j) return 0;
if(s[i][j]>=0) return s[i][j];
s[i][j]=999999;
for(int k=i;k<j;++k)
{
int tem=f(i,k)+f(k+1,j)+a[i][1]*a[k][2]*a[j][2];
s[i][j]=(s[i][j]<tem) ? s[i][j]:tem;
}
return s[i][j];
}
int main()
{
int num;
while(1)
{
scanf("%d",&num);
if(num==0) break;
memset(s,-1,sizeof(s));
for(int i=1;i<=num;++i)
scanf("%d%d",&a[i][1],&a[i][2]);
printf("%d\n",f(1,num));
}
return 0;
}
吐槽下这个oj题目没有给定n的范围,纠结。。。