• 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];
        }
    };
  • 相关阅读:
    正则表达式随笔
    linux 命令大全
    oracle merge into
    存储过程else if
    存储过程 loop
    存储过程 函数
    存储过程使用集合来存储查询
    存储过程使用游标和索引
    存储过程使用%rowtype定义游标类型的变量提取emp数据
    ORACLE 存储过程 like 样例
  • 原文地址:https://www.cnblogs.com/wenruo/p/12717004.html
Copyright © 2020-2023  润新知