1. 程式人生 > 實用技巧 >能量項鍊

能量項鍊

題目描述

在Mars星球上,每個Mars人都隨身佩帶著一串能量項鍊。在項鍊上有N顆能量珠。能量珠是一顆有頭標記和尾標記的珠子,這些標記對應著某個正整數。並且,對於相鄰的兩顆珠子,前一顆珠子的尾標記必定等於後一顆珠子的頭標記。因為只有這樣,通過吸盤——Mars人吸收能量的器官的作用,這兩顆珠子才能聚合成一顆珠子,同時釋放出可被吸盤吸收的能量。如果一顆能量珠頭標記為m,尾標記為r,後一顆能量珠頭標記為r,尾標記為n,則聚合後釋放出m×r×nMars單位的能量,新珠子頭標記為m,尾標記為n。
當需要時,Mars人就用吸盤夾住相鄰的兩顆珠子,通過聚合得到能量,直到項鍊上只剩下一顆珠子為止。顯然,不同的聚合順序得到的總能量是不一樣的。請設計一個聚合順序使得一串珠子聚合後釋放出的總能量最大。
例如,設N=4,四顆珠子頭標記與尾標記分別為(2,3),(3,5),(5,10),(10,2)。我們用記號⨂表示兩顆珠子的聚合操作,(j \bigotimes k)(jk)表示j,k兩顆珠子聚合後釋放出的能量,則4,1兩顆珠子聚合後所釋放的能量為(4 \bigotimes1)=10 \times2 \times3=60(41)=10×2×3=60,這一串項鍊可以得到最優值的一個聚合順序所釋放出的總能量為(((4 \bigotimes1) \bigotimes2) \bigotimes3)=(((41)2)3)=10 \times2 \times3+10 \times3 \times5+10 \times5 \times10=71010×2×3+10×3×5+10×5×10=710
現在給你一串項鍊,項鍊上有n顆珠子,相鄰兩顆珠子可以合併成一個,合併同時會放出一定的能量,不同珠子合併放出能量不相同,請問按怎樣的次序合併才能使得釋放的能量最多?

輸入描述:

第一行一個正整數n
第二行n個不超過1000的正整數,第i(1 \le i \le n)i(1in)個數為第i顆珠子的頭標記,當i \neq ni=n時第i顆珠子的尾標記等於第i+1顆珠子的頭標記,當i=n時第i顆珠子的尾標記等於第1顆珠子的頭標記。
至於珠子的順序,你可以這樣確定:將項鍊放在桌面上,不要出現交叉,隨機指定一顆珠子為第一顆珠子,按順時針確定其它珠子的順序。

輸出描述:

輸出只有一行,一個不超過2.1 \times10^92.1×109的正整數,表示最優聚合順序所釋放的能量。

輸入

4
2 3 5 10

輸出

710
#include<bits/stdc++.h>
using namespace std;
const int N = 2e2 + 7;
int a[N], dp[N][N], n;
int main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> a[i], a[i + n] = a[i];
    a[2 * n + 1] = a[1];
    for (int len = 2; len <= n; len++) {
        for (int l = 1; l <= 2 * n - len + 1; l++) {
            int r = l + len - 1;
            for (int k = l; k < r; k++) {
                //合併[l,k]和[k+1,r]消耗為[a[l],a[k]]*[a[k+1],a[r + 1]] = a[l] * a[k + 1] *a[r + 1]
                dp[l][r] = max(dp[l][r], dp[l][k] + dp[k + 1][r] + a[l] * a[r + 1] * a[k + 1]);
            //dp[i][i + 1] = dp[i][i] + dp[i + 1][i + 1] + a[i] * a[i + 1] * a[i + 2]
                //dp[l][j] = dp[i][k] + dp[k + 1][r] + a[l] * a[k + 1] * a[r + 1]
            }
        }
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) ans = max(ans, dp[i][i + n - 1]);
    cout << ans << endl;
    return 0;
}