問題:給定數列 a[1..n],每次可移除一個內部元素 a[i](1 < i < 當前長度),獲得代價 a[i-1] * a[i] * a[i+1]。剩餘元素合併。求將數列縮減至兩端元素的最小總代價。
定義 dp[l][r] = 將區間 [l, r] 內部元素全部移除(只剩 a[l] 和 a[r])的最小代價。答案為 dp[1][n]。
考慮區間 [l, r] 最後移除的元素為 k (l < k < r)。移除 k 時,其左右鄰居必為 a[l] 和 a[r](因為內部已被清空)。故:
dp[l][r] = min_{l
dp[l][l+1] = 0(無內部元素)。int a[105], dp[105][105];
int n;
int dfs(int l, int r) {
if (l + 1 >= r) return 0; // 區間長度 ≤ 2
if (dp[l][r] != -1) return dp[l][r];
int ans = INF;
for (int k = l+1; k < r; ++k)
ans = min(ans, dfs(l, k) + dfs(k, r) + a[l]*a[k]*a[r]);
return dp[l][r] = ans;
}
int main() {
while (cin >> n) {
for (int i = 1; i <= n; ++i) cin >> a[i];
memset(dp, -1, sizeof dp);
cout << dfs(1, n) << endl;
}
return 0;
}
O(n²),n ≤ 100。O(n) 分割點,總時間 O(n³) ≈ 10⁶,極快。O(n²)。「最後移除誰」決定了左右子區間獨立計算,這是區間 DP 的典型「最優子結構」。代價公式 a[l]*a[k]*a[r] 反映了移除 k 時其鄰居已固定為區間端點。