之前写了这道题的递归解法,虽说是做出来了,但现在想想其实就是对着别人的代码套下来的,当时自己对这道题的理解还是十分不够,最近开始认真学习dp,其实也是有点入门了的感觉,找书又看了这道题,终于有了更进一步的理解,自己又重新敲了一遍代码,感觉还是有收获的,不过对这道题仍然不敢说“理解”,现在终于知道,自己的水平还差得远呢。
这是上次做这道题时写的博客http://blog.csdn.net/harrypoirot/article/details/12112117
这次做这道题与上次的不同在于使用的是递推而非递归的方法,之前对递推一直有些抵触,因为觉得很难理解,后来找到机会请前辈学长给讲了一下括号匹配这道题(poj-1141),算是对递推法有了个初步的理解,进一步的理解是看《计算机算法设计与分析》这本书得出的,说实话,不知道是不是我比较笨的原因,感觉看这本书比看《算法导论》、《算法设计与信息学竞赛》什么的书更好理解。。。
好吧,废话扯这么多,先把代码贴上,然后好总结
#include<cstdio>
#include<cstring>
int rem[35][35];
int main()
{
int num,n[35];
while(scanf("%d",&num)&&num)
{
scanf("%d",&n[0]);
for(int i=1;i<num;++i)
scanf("%d%d",&n[i],&n[i]);
scanf("%d",&n[num]);
memset(rem,0,sizeof(rem));
for(int p=1;p<num;++p)
{
for(int i=1;i+p<=num;++i)
{
int j=i+p;
rem[i][j]=99999999;
for(int k=i;k<j;++k)
{
if(rem[i][j]>rem[i][k]+rem[k+1][j]+n[i-1]*n[k]*n[j])
rem[i][j]=rem[i][k]+rem[k+1][j]+n[i-1]*n[k]*n[j];
}
}
}
printf("%d\n",rem[1][num]);
}
return 0;
}
上次做这道题的时候用了二维数组来存储矩阵信息,后来才知道原来用一维数组存储就可以,因为,前后两个数组的列、行一定是一样的,所以只要将第一个数组的行存在‘0’位,之后两个相邻相同数据只存储一个就行了~~
之后开始递推填充记录信息
rem[i][j]代表的是i到j个矩阵相乘的最优信息,易知i=j时,也就是只有一个矩阵,用不着计算,即为0,i<j时,依次尝试将矩阵链断开,取其中最优值作为该处的rem,具体实现方法代码已经给出~~