【區間 dp】A023_LC_合併石頭的最低成本(窮舉分割點)

一、Problem

有 N 堆石頭排成一排,第 i 堆中有 stones[i] 塊石頭。

每次移動(move)需要將連續的 K 堆石頭合併爲一堆,而這個移動的成本爲這 K 堆石頭的總數。

找出把所有石頭合併成一堆的最低成本。如果不可能,返回 -1 。

Input: stones = [3,2,4,1], K = 2
Output: 20
Explanation: 
We start with [3, 2, 4, 1].
We merge [3, 2] for a cost of 5, and we are left with [5, 4, 1].
We merge [4, 1] for a cost of 5, and we are left with [5, 5].
We merge [5, 5] for a cost of 10, and we are left with [10].
The total cost was 20, and this is the minimum possible.

Note:

1 <= stones.length <= 30
2 <= K <= 30
1 <= stones[i] <= 100

二、Solution

方法一:記憶化搜索

  • 定義狀態
    • f[i][j][k]f[i][j][k] 表示將區間 [i,j][i, j] 中的幾堆石子合併成 kk 堆需要的最小代價
  • 思考初始化:
    • f[0:][0:][0:]=INFf[0:][0:][0:] = INF
    • f[i][i][1]=0f[i][i][1] = 0 石子不用動就可以了…
  • 思考狀態轉移方程
    • 這裏直接寫轉移會比較繁瑣,所以直接講思路:因爲我們不知道合併哪些區間可以使得代價最小,所以我們需要窮舉一下每種大小的區間 len(len = r-l+1)
    • 且在區間 [l, r] 中,我們也不清楚具體要合併哪兩對堆(如果將區間劃分成兩半)所以我們需要枚舉一下切分點 p 在區間 [l, r] 中的位置
    • 切分位置 p 我們知道了,但是我們還不知道要將這兩部分石子合併成幾堆,所以我們還需要枚舉一下石子的對數 kkrl+1k(k \leqslant r-l+1)
  • 思考輸出f[1][n][1]f[1][n][1]
class Solution {
    public int mergeStones(int[] a, int K) {
        int n = a.length, INF = 0x3f3f3f3f, s[] = new int[n+1], f[][][] = new int[n+1][n+1][n+1];
        if ((n-1) % (K-1) != 0)
            return -1;
        if (n < 2)
            return 0;
        for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            Arrays.fill(f[i][j], INF);
        }
        for (int i = 1; i <= n; i++) {
            s[i] = s[i-1] + a[i-1];
            f[i][i][1] = 0;
        }

        for (int len = 2; len <= n; len++)
        for (int l = 1; l <= n - len + 1; l++) {
            int r = l + len - 1;
            
            for (int k = 2; k <= len; k++)
            for (int p = l; p < r; p++) {
                f[l][r][k] = Math.min(f[l][r][k], f[l][p][k-1] + f[p+1][r][1]);
            }
            // 由於上面的k是遞增的,所以到達K時,f[l][r][K]一定是最小(最優)此時
            f[l][r][1] = Math.min(f[l][r][1], f[l][r][K] + s[r] - s[l-1]); 
        }
        return f[1][n][1];
    }
}
複雜度分析
  • 時間複雜度:O(n3×K)O(n^3 × K)
  • 空間複雜度:O(n3)O(n^3)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章