There are N
piles of stones arranged in a row. The i
-th pile has stones[i]
stones.
A 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 mergestone[i]
~stones[j]
intom
piles.Initial status
dp[i][i][1] = 0
anddp[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来的思路清晰一点