1000. Minimum Cost to Merge Stones

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zjucor/article/details/88086813

There are N piles of stones arranged in a row.  The i-th pile has stones[i] stones.

move consists of merging exactly K consecutive piles into one pile, and the cost of this move is equal to the total number of stones in these K piles.

Find the minimum cost to merge all piles of stones into one pile.  If it is impossible, return -1.

Example 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.

Example 2:

Input: stones = [3,2,4,1], K = 3
Output: -1
Explanation: After any merge operation, there are 2 piles left, and we can't merge anymore.  So the task is impossible.

Example 3:

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

Note:

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

思路:DP,有多个变量就有多少个维度,惭愧,没有写出来

刚开始肯定能想到是区间dp,dp[i][j]表示[i,j]范围合并成1堆,但是这样递归不下去,dp[i][j]=dp[i][mid]+??

不得已,dp数组必须额外增加一个维度,dp[i][j][k]表示[i,j]范围合并成k堆

https://leetcode.com/problems/minimum-cost-to-merge-stones/discuss/247567/Python-Top-Down-DP-52ms

dp[i][j][m] means the cost needed to merge stone[i] ~ stones[j] into m piles.

Initial status dp[i][i][1] = 0 and dp[i][i][m] = infinity

dp[i][j][m] = min(dp[i][mid][1] + dp[mid + 1][j][m - 1] + stonesNumber[i][j])

class Solution(object):
    def mergeStones(self, stones, K):
        """
        :type stones: List[int]
        :type K: int
        :rtype: int
        """
        n=len(stones)
        if n==1: return 0
        if n<K: return -1
        if (n-K)%(K-1): return -1
        
        inf = float('inf')
        memo = {}
        def dp(i, j, m):
            if (i, j, m) in memo: return memo[(i, j, m)]
            if i==j:
                res = 0 if m==1 else inf
                memo[(i, j, m)] = res
                return res
            
            if m==1:
                res = dp(i,j,K) + sum(stones[i:j+1])
            else:
                res = inf
                for mid in range(i,j,K-1): # length must be K+n*(K-1)
                    res = min(res, dp(i,mid,1)+dp(mid+1,j,m-1))
            memo[(i, j, m)] = res
            return res
        
        res = dp(0, n-1, 1)
        return res if res<inf else -1
    

直接用dp数组还得先算m大的,计算方向比较麻烦,不如直接递归+memo来的思路清晰一点

猜你喜欢

转载自blog.csdn.net/zjucor/article/details/88086813