区间dp: dp[l][r][0]表示区间l~r作为左子树的最小开销
dp[l][r][1]表示区间l~r作为右子树的最小开销
对于区间[l][r]枚举根节点k,分别计算l~r作为左子树和作为右子树的最小代价
在l~r区间上,以k为根的树作为左子树的代价可以计算为val[k]*val[r+1]+dp[l][k-1][0]+dp[k+1][r][1]。
同理,作为右子树的代价可以计算为dp[l][r][1]=min(dp[l][r][1],val[k]*val[l-1]+dp[l][k-1][0]+dp[k+1][r][1])。
#include<bits/stdc++.h>
using namespace std;
const int N=305,INF=0x3fffffff;
int dp[N][N][2],val[N];
int main()
{
int m,n,i,j,k,t;
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&val[i]);
for(i=1;i<=n;i++) dp[i][i][1]=val[i]*val[i-1],dp[i][i][0]=val[i]*val[i+1];
for(i=1;i<=n;i++) {
for(j=1;j+i<=n;j++)
{
int l=j,r=j+i; dp[l][r][0]=dp[l][r][1]=INF;
for(k=l;k<=r;k++)
{
dp[l][r][0]=min(dp[l][r][0],val[k]*val[r+1]+dp[l][k-1][0]+dp[k+1][r][1]);
dp[l][r][1]=min(dp[l][r][1],val[k]*val[l-1]+dp[l][k-1][0]+dp[k+1][r][1]);
}
}
}
printf("%d",min(dp[1][n][0],dp[1][n][1]));
}