★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/10464869.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
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
有 N
堆石头排成一排,第 i
堆中有 stones[i]
块石头。
每次移动(move)需要将连续的 K
堆石头合并为一堆,而这个移动的成本为这 K
堆石头的总数。
找出把所有石头合并成一堆的最低成本。如果不可能,返回 -1
。
示例 1:
输入:stones = [3,2,4,1], K = 2 输出:20 解释: 从 [3, 2, 4, 1] 开始。 合并 [3, 2],成本为 5,剩下 [5, 4, 1]。 合并 [4, 1],成本为 5,剩下 [5, 5]。 合并 [5, 5],成本为 10,剩下 [10]。 总成本 20,这是可能的最小值。
示例 2:
输入:stones = [3,2,4,1], K = 3 输出:-1 解释:任何合并操作后,都会剩下 2 堆,我们无法再进行合并。所以这项任务是不可能完成的。.
示例 3:
输入:stones = [3,5,1,2,6], K = 3 输出:25 解释: 从 [3, 5, 1, 2, 6] 开始。 合并 [5, 1, 2],成本为 8,剩下 [3, 8, 6]。 合并 [3, 8, 6],成本为 17,剩下 [17]。 总成本 25,这是可能的最小值。
提示:
1 <= stones.length <= 30
2 <= K <= 30
1 <= stones[i] <= 100
1 class Solution { 2 struct State: Hashable { 3 var range: Range<Int>, pileCount: Int 4 } 5 6 func mergeStones(_ stones: [Int], _ K: Int) -> Int { 7 guard (stones.count - 1) % (K - 1) == 0 else { 8 return -1 9 } 10 11 let prefixSum: [Int] = stones.reduce(into: [0]) { $0.append($0.last! + $1) } 12 func sum(in range: Range<Int>) -> Int { 13 return prefixSum[range.upperBound] - prefixSum[range.lowerBound] 14 } 15 16 var states: [State: Int] = [:] 17 func minCost(in range: Range<Int>, pileCount: Int) -> Int { 18 if let result = states[State(range: range, pileCount: pileCount)] { 19 return result 20 } 21 guard range.count != pileCount else { 22 return 0 23 } 24 guard pileCount != 1 else { 25 return minCost(in: range, pileCount: K) + sum(in: range) 26 } 27 28 var result = Int.max 29 for split in stride(from: range.lowerBound + 1, to: range.upperBound, by: K - 1) { 30 let first = minCost(in: range.lowerBound..<split, pileCount: 1) 31 let second = minCost(in: split..<range.upperBound, pileCount: pileCount - 1) 32 33 result = min(result, first + second) 34 } 35 36 states[State(range: range, pileCount: pileCount)] = result 37 return result 38 } 39 40 return minCost(in: stones.indices, pileCount: 1) 41 } 42 }
44ms
1 class Solution { 2 private var cache = [[[Int?]]]() 3 private var prefixSum = [Int]() 4 private var K = 0 5 func mergeStones(_ stones: [Int], _ K: Int) -> Int { 6 guard stones.count != 1 else { return 0 } 7 guard (stones.count - 1) % (K - 1) == 0 else { return -1 } 8 guard stones.count >= K else { return -1 } 9 10 self.K = K 11 12 for i in 0..<stones.count { 13 var iArr = [[Int?]]() 14 for j in 0..<stones.count { 15 var jArr = [Int?]() 16 for k in 0...K { 17 if i == j || k == j - i + 1 { 18 jArr.append(0) 19 } else { 20 jArr.append(nil) 21 } 22 } 23 iArr.append(jArr) 24 } 25 cache.append(iArr) 26 } 27 28 prefixSum = [0] 29 30 for stone in stones { 31 prefixSum.append(prefixSum[prefixSum.count - 1] + stone) 32 } 33 34 return dp(0, stones.count - 1, 1) 35 } 36 37 private func dp(_ i: Int, _ j: Int, _ k: Int) -> Int { 38 if let val = cache[i][j][k] { 39 return val 40 } 41 42 let result: Int 43 44 if k == 1 { 45 result = dp(i, j, K) + prefixSum[j + 1] - prefixSum[i] 46 } else { 47 var minimum = 9999999999999 48 var t = i 49 while t < j { 50 minimum = min(minimum, dp(i, t, 1) + dp(t + 1, j, k - 1)) 51 t += (K - 1) 52 } 53 result = minimum 54 } 55 56 cache[i][j][k] = result 57 return result 58 } 59 }
Runtime: 380 ms
1 class Solution { 2 func mergeStones(_ stones: [Int], _ K: Int) -> Int { 3 var n:Int = stones.count 4 var pre:[Int] = [Int](repeating:0,count:n + 1) 5 for i in 1...n 6 { 7 pre[i] = pre[i - 1] + stones[i - 1] 8 } 9 var inf:Int = 1000000000 10 var dp:[[[Int]]] = [[[Int]]](repeating:[[Int]](repeating:[Int](repeating:inf,count:205),count:205),count:205) 11 for i in 1...n 12 { 13 dp[i][i][1] = 0 14 } 15 for len in 1...n 16 { 17 var i:Int = 1 18 while(i + len - 1 <= n) 19 { 20 var j:Int = i + len - 1 21 if len >= 2 22 { 23 for k in 2...len 24 { 25 var t:Int = i 26 while(t + 1 <= j) 27 { 28 dp[i][j][k] = min(dp[i][j][k], dp[i][t][k - 1] + dp[t + 1][j][1]) 29 t += 1 30 } 31 } 32 } 33 dp[i][j][1] = min(dp[i][j][1], dp[i][j][K] + pre[j] - pre[i - 1]) 34 i += 1 35 } 36 } 37 if dp[1][n][1] >= inf 38 { 39 return -1 40 } 41 return dp[1][n][1] 42 } 43 }