首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

POJ 1651 Multiplication Puzzle:區間 DP 求最小乘法代價

     編輯:C++ 入門

POJ 1651 Multiplication Puzzle — 區間 DP 經典入門

問題:給定數列 a[1..n],每次可移除一個內部元素 a[i](1 < i < 當前長度),獲得代價 a[i-1] * a[i] * a[i+1]。剩餘元素合併。求將數列縮減至兩端元素的最小總代價。

DP 定義與轉移

定義 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 時其鄰居已固定為區間端點。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved