There are n piles of stones arranged in a row. The ith pile has stones[i] stones.
A move consists of merging exactly kconsecutive piles into one pile, and the cost of this move is equal to the total number of stones in these k piles.
Return the minimum cost to merge all piles of stones into one pile. If it is impossible, return -1.
Input: stones =[3,2,4,1], k =2Output: 20Explanation: 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 thisis the minimum possible.
Input: stones =[3,2,4,1], k =3Output: -1Explanation: After any merge operation, there are 2 piles left, and we can't merge anymore. So the task is impossible.
Input: stones =[3,5,1,2,6], k =3Output: 25Explanation: 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 thisis the minimum possible.
We use DP to track the minimum cost to merge subarrays of stones into a certain number of piles. We use prefix sums to quickly calculate the cost of merging. The key is to only merge when the number of piles is reducible to 1 by repeatedly merging k piles.
classSolution:
defmergeStones(self, stones: list[int], k: int) -> int:
n = len(stones)
if (n-1) % (k-1):
return-1 prefix = [0]*(n+1)
for i in range(n):
prefix[i+1] = prefix[i] + stones[i]
dp = [[[float('inf')] * (k+1) for _ in range(n)] for _ in range(n)]
for i in range(n):
dp[i][i][1] =0for l in range(2, n+1):
for i in range(n-l+1):
j = i+l-1for m in range(2, k+1):
for mid in range(i, j, k-1):
dp[i][j][m] = min(dp[i][j][m], dp[i][mid][1] + dp[mid+1][j][m-1])
if (l-1) % (k-1) ==0:
dp[i][j][1] = dp[i][j][k] + prefix[j+1] - prefix[i]
return dp[0][n-1][1]