[Swift]LeetCode1000. 合併石頭的最低成本 | Minimum Cost to Merge Stones

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-yhmnfwtj-md.html 
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html

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

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

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

Example 1:app

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:ide

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:this

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:spa

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

有 N 堆石頭排成一排,第 i 堆中有 stones[i] 塊石頭。code

每次移動(move)須要將連續的 K 堆石頭合併爲一堆,而這個移動的成本爲這 K 堆石頭的總數。htm

找出把全部石頭合併成一堆的最低成本。若是不可能,返回 -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

32ms
 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

Memory Usage: 19.3 MB
 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 }
相關文章
相關標籤/搜索