zoukankan      html  css  js  c++  java
  • [Swift]LeetCode1000. 合并石头的最低成本 | Minimum Cost to Merge Stones

    ★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
    ➤微信公众号:山青咏芝(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

    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 }
  • 相关阅读:
    实现带有头结点的链表
    数据结构之链式线性表
    HDU 1010 dfs+奇偶剪枝
    数据结构之顺序线性表
    POJ 1753 dfs+枚举
    HDU 4277 dfs+set去重
    平衡二叉树
    线性素数筛+欧拉线性筛(证明)
    dp--2019南昌网络赛B-Match Stick Game
    线段树+单调栈+前缀和--2019icpc南昌网络赛I
  • 原文地址:https://www.cnblogs.com/strengthen/p/10464869.html
Copyright © 2011-2022 走看看