LeetCode 1000. Minimum Cost to Merge Stones (區間 DP)

根據寒神題解 https://leetcode.com/problems/minimum-cost-to-merge-stones/discuss/247567/JavaC%2B%2BPython-DP

題意:

每次可以把連續 K 堆石頭合成一堆,花費是 K 堆之和,問最小花費多少可以把全部石頭合成 1 堆。不能做到的話,返回 -1。

題解:

因爲,每次把 K 堆變成 1 堆,也就是說每次都減去 K-1 堆,最後剩下 1 堆,所以只有在  (n - 1) % (K - 1) == 0  纔可以合成 1 堆。

 

 dp[i][j] 表示  stones[i..j]  儘可能合併之後,花費的最小值。

 

然後枚舉第i個石頭和前幾個石頭合成了一堆。 只有長度爲  1 + (K-1)*x  時才能合成一堆,所以枚舉長度每次加  K - 1 。

 

class Solution {
public:
    int mergeStones(vector<int>& stones, int K) {
        int n = stones.size();
        if ((n-1) % (K-1)) return -1;
        vector<int> prefix(n + 1);
        for (int i = 1; i <= n; i++) prefix[i] = prefix[i-1] + stones[i - 1];
        vector<vector<int>> dp(n, vector<int>(n, 0));
        // 當j-i < K 時不需要合併 所以值爲 0
        for (int l = K - 1; l < n; l++) {
            for (int s = 0; s + l < n; s++) {
                int e = s + l;
                dp[s][e] = INT_MAX;
                for (int m = s; m < e; m += K - 1) {
                    dp[s][e] = min(dp[s][e], dp[s][m] + dp[m + 1][e]);
                }
                // l % (K - 1) == 0 剛好可以合成一堆
                // 因爲枚舉的是左邊合成一堆,所以左右相加之後一定大於一堆,不是最簡狀態
                // 所以需要再次合併 合併需要的值就是區間和
                if (l % (K - 1) == 0) {
                    dp[s][e] += prefix[e + 1] - prefix[s];
                }
            }
        }
        return dp[0][n - 1];
    }
};

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章