题目链接:https://vjudge.net/problem/NBUT-1003
思路:也是和紫书上的一样,如果最后一次乘法是第k个,则从A1,A2,....Ak和Ak+1,Ak+2......An两个子序列都是最优乘法了,所以我们只需保证两个子结构最优,而子结构也是可以这样划分的,所以我们每次考虑的问题就是,把Ai,Ai+1...Aj乘起来的最少乘法次数,用dp[i][j]表示这个问题的值,有
dp[i][j]=min{dp[i][k]+dp[k+1][j]+pi-1*pk*pj}
关键是递推的次序要搞明白,当时就没做出来,还是参考大神的代码,按照j-i递增的方向递推,因为长区间的值依赖于短区间的值。具体实现还是需要斟酌一下的,代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
typedef long long ll;
const int maxn=210;
const int INF=0x3f3f3f3f;
ll dp[maxn][maxn];
ll p[maxn];
/*
递推方向如何写还是比较难想的,长区间的值依赖于短区间,
所以递推的方向为j-i的递增方向,i为集合左端,j为集合右端。
*/
int main()
{
ll n;
while(scanf("%lld",&n)!=EOF)
{
for(int i=0;i<n+1;i++)
{
scanf("%lld",&p[i]);
}
//长度为1的矩阵集合,都归0,没有乘法计算。
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(i==j)
dp[i][j]==0;
}
}
for(int x=2;x<=n;x++)//矩阵集合的长度,2,3....n
{
for(int i=1;i<=n-x+1;i++)
{
//按照j-i递增的顺序递推,因为j是矩阵集合的右端,而长区间的值依赖于短区间
int j=x+i-1;
dp[i][j]=INF;
for(int k=i;k<j;k++)
{
dp[i][j]=min(dp[i][j],dp[i][k]+dp[k+1][j]+p[i-1]*p[k]*p[j]);
}
}
}
printf("%lld\n",dp[1][n]);
}
return 0;
}