#牛客春招刷题训练营# + 链接

区间dp经典题啦

先套路复制一遍解环,然后用dp[i][j]表示第i颗到第j颗聚合完之后的最优值,每次枚举最后是哪两段聚合就可以

#include <iostream>
using namespace std;

using ll = long long;
const int mod=1e9+7;
const int N=210;
ll dp[N][N], a[N];

inline void getmax(ll &x, ll y)
{
    if (y>x) x=y;
}

int main() {
    int n,m;
    scanf("%d", &n);
    for (int i=1;i<=n;i++) {
        scanf("%lld", &a[i]);
        a[n+i]=a[i];
    }
    m = n+n;
    a[m+1]=a[1];
    a[m+2]=a[2];
    for (int i=1;i<=m;i++) dp[i][i+1]=a[i]*a[i+1]*a[i+2];
    for (int x=3;x<=n;x++) {
        for (int i=1,j=x;j<=m;i++,j++) {
            for (int k=i;k<j;k++) {
                getmax(dp[i][j], dp[i][k]+dp[k+1][j]+a[i]*a[j+1]*a[k+1]);
            }
        }
    }
    ll ans = 0;
    for (int i=1;i<=n;i++) {
        getmax(ans, dp[i][i+n-1]);
    }
    printf("%lld\n", ans%mod);
    return 0;
}