解题思路:动态规划

这是一道区间dp的题目。首先第一步是把区间从n扩展到2n,这样就不用尾首循环了。

接下来按照区间大小,从小到大循环,先计算小区间的最优解,再计算大区间的最优解。

状态转移方程:dp[l][r] = max(dp[l][j] + dp[j][r] + a[l] * a[j] * a[r]), j ∈ [ l + 1, r - 1 ]

注意本题的数据范围:由于珠子的值满足val <= 1000,因此每次获取的能量不超过10^9;n <= 100表示最多100个珠子,故而能量总和不超过10^11。因此使用long long,并且计算的中途不要对109+7取模(如果你在计算中途对109+7取模,则取模后的值就不是最大值了,可能导致后续的dp错误)。

下面贴出cpp代码。

#include <iostream>
#include <vector>
using namespace std;

int main() {
    const int mod = 1e9 + 7;
    int n;
    cin >> n;
    vector<int> a(n + n);
    vector<vector<long long>> dp(n + n, vector<long long>(n + n, 0));
    for (int i = 0; i < n; ++i) {
        cin >> a[i];
        a[i + n] = a[i];
    }
    for (int i = 2; i < n; ++i) {
        for (int l = 0; l < n; ++l) {
            int r = l + i;
            for (int j = l + 1; j < r; ++j) {
                dp[l][r] = max(dp[l][r], dp[l][j] + dp[j][r] + a[l] * a[j] * a[r]);
            }
            if(r < n) dp[l + n][r + n] = dp[l][r];
        }
    }
    long long ans = 0;
    for (int l = 0; l < n; ++l) {
        int r = l + n;
        for (int j = l + 1; j < r; ++j) {
            ans = max(ans, dp[l][j] + dp[j][r] + a[l] * a[j] * a[r]);
        }
    }
    cout << (ans % mod);
}