★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公衆號:山青詠芝(shanqingyongzhi)
➤博客園地址:山青詠芝(https://www.cnblogs.com/strengthen/)
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:http://www.javashuo.com/article/p-biwtyvnz-ks.html
➤若是連接不是山青詠芝的博客園地址,則多是爬取做者的文章。
➤原文已修改更新!強烈建議點擊原文地址閱讀!支持做者!支持原創!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★html
Alex and Lee continue their games with piles of stones. There are a number of piles arranged in a row, and each pile has a positive integer number of stones piles[i]
. The objective of the game is to end with the most stones. git
Alex and Lee take turns, with Alex starting first. Initially, M = 1
.github
On each player's turn, that player can take all the stones in the first X
remaining piles, where 1 <= X <= 2M
. Then, we set M = max(M, X)
.微信
The game continues until all the stones have been taken.ide
Assuming Alex and Lee play optimally, return the maximum number of stones Alex can get.this
Example 1:spa
Input: piles = [2,7,9,4,4] Output: 10 Explanation: If Alex takes one pile at the beginning, Lee takes two piles, then Alex takes 2 piles again. Alex can get 2 + 4 + 4 = 10 piles in total. If Alex takes two piles at the beginning, then Lee can take all three piles left. In this case, Alex get 2 + 7 = 9 piles in total. So we return 10 since it's larger.
Constraints:rest
1 <= piles.length <= 100
1 <= piles[i] <= 10 ^ 4
亞歷克斯和李繼續他們的石子游戲。許多堆石子 排成一行,每堆都有正整數顆石子 piles[i]
。遊戲以誰手中的石子最多來決出勝負。code
亞歷克斯和李輪流進行,亞歷克斯先開始。最初,M = 1
。htm
在每一個玩家的回合中,該玩家能夠拿走剩下的 前 X
堆的全部石子,其中 1 <= X <= 2M
。而後,令 M = max(M, X)
。
遊戲一直持續到全部石子都被拿走。
假設亞歷克斯和李都發揮出最佳水平,返回亞歷克斯能夠獲得的最大數量的石頭。
示例:
輸入:piles = [2,7,9,4,4] 輸出:10 解釋: 若是亞歷克斯在開始時拿走一堆石子,李拿走兩堆,接着亞歷克斯也拿走兩堆。在這種狀況下,亞歷克斯能夠拿到 2 + 4 + 4 = 10 顆石子。 若是亞歷克斯在開始時拿走兩堆石子,那麼李就能夠拿走剩下所有三堆石子。在這種狀況下,亞歷克斯能夠拿到 2 + 7 = 9 顆石子。 因此咱們返回更大的 10。
提示:
1 <= piles.length <= 100
1 <= piles[i] <= 10 ^ 4
1 class Solution { 2 private var sums = [Int](repeating: 0, count: 101) 3 private var hash = [[Int]](repeating: [Int](repeating: 0, count: 101), count: 101) 4 func stoneGameII(_ piles: [Int]) -> Int { 5 let N = piles.count 6 if N == 0 { return 0 } 7 sums[N-1] = piles[N-1] 8 for i in stride(from: N-2, to: -1, by: -1) { 9 sums[i] = sums[i+1] + piles[i] 10 } 11 12 return helper(piles, 0, 1) 13 } 14 15 16 private func helper(_ a: [Int], _ i: Int, _ M: Int) -> Int { 17 if i == a.count { return 0 } 18 if 2*M >= a.count - i { return sums[i] } 19 if hash[i][M] != 0 { return hash[i][M] } 20 21 var minv = Int.max //the min value the next player can get 22 for x in 1..<2*M+1 { 23 minv = min(minv, helper(a, i+x, max(M,x))) 24 } 25 hash[i][M] = sums[i] - minv //max stones = all the left stones - the min stones next player can get 26 return hash[i][M] 27 } 28 }
Runtime: 16 ms
1 class Solution { 2 func stoneGameII(_ piles: [Int]) -> Int { 3 var n:Int = piles.count 4 var sums:[Int] = [Int](repeating:0,count:n + 1) 5 for i in stride(from:n - 1,through:0,by:-1) 6 { 7 sums[i] = piles[i] + sums[i+1] 8 } 9 var dp:[[Int]] = [[Int]](repeating:[Int](repeating:0,count:n + 1),count:n) 10 for i in stride(from:n - 1,through:0,by:-1) 11 { 12 for j in 1...n 13 { 14 if 2 * j >= n - i 15 { 16 dp[i][j]=sums[i] 17 } 18 else 19 { 20 for k in 1...(2*j) 21 { 22 let nextM:Int = max(k,j) 23 dp[i][j] = max(dp[i][j],sums[i] - dp[i+k][nextM]) 24 } 25 } 26 } 27 } 28 return dp[0][1] 29 } 30 }
1 class Solution { 2 func stoneGameII(_ piles: [Int]) -> Int { 3 guard !piles.isEmpty else { return 0 } 4 5 var hash = [Key:Int]() 6 var sums = Array(repeating: 0, count: piles.count) 7 sums[0] = piles[0] 8 for i in 1..<piles.count { 9 sums[i] = sums[i-1] + piles[i] 10 } 11 return _stoneGameII(sums, 0, 1, &hash) 12 } 13 14 func _stoneGameII(_ sums: [Int], _ i: Int, _ m: Int, _ hash: inout [Key:Int]) -> Int { 15 if i >= sums.count { return 0 } 16 17 let key = Key(i,m) 18 if let result = hash[key] { return result } 19 20 var result = Int.max 21 for x in (i..<min(sums.count, (i + m * 2))) { 22 result = min(result, _stoneGameII(sums, x+1, max(m, x - i + 1), &hash)) 23 } 24 25 result = sums[sums.count - 1] - (i == 0 ? 0 : sums[i - 1]) - result 26 27 hash[key] = result 28 return result 29 } 30 } 31 32 struct Key: Hashable { 33 let i: Int 34 let m: Int 35 36 init(_ i: Int, _ m: Int) { 37 self.i = i 38 self.m = m 39 } 40 }
40ms
1 class Solution { 2 var m = [[Int]]() 3 func stoneGameII(_ piles: [Int]) -> Int { 4 var sum = piles.reduce(0){$0 + $1} 5 m = [[Int]](repeating:[Int](repeating: Int.min, count: 2 * piles.count), count: piles.count) 6 let diff = dfsHelper(piles, 0, 1) 7 return (sum - diff) / 2 + diff 8 } 9 10 fileprivate func dfsHelper(_ piles:[Int], _ idx:Int, _ M:Int) -> Int { 11 12 13 if idx >= piles.count { 14 return 0 15 } 16 if m[idx][M] > 0 { return m[idx][M] } 17 18 var sum = 0 19 for i in idx...min(idx + 2 * M - 1, piles.count - 1) { 20 sum += piles[i] 21 m[idx][M] = max(m[idx][M], sum - dfsHelper(piles, i+1, max(M, (i - idx)+1))) 22 } 23 return m[idx][M] 24 } 25 }
192ms
1 class Solution { 2 func stoneGameII(_ piles: [Int]) -> Int { 3 guard !piles.isEmpty else { return 0 } 4 5 var hash = [Key:Int]() 6 return _stoneGameII(piles, 0, 1, true, &hash) 7 } 8 9 func _stoneGameII(_ piles: [Int], _ i: Int, _ m: Int, _ player: Bool, _ hash: inout [Key:Int]) -> Int { 10 if i >= piles.count { return 0 } 11 12 let key = Key(i,m,player) 13 if let result = hash[key] { return result } 14 15 var result = player ? Int.min : Int.max 16 for x in (i..<min(piles.count, (i + m * 2))) { 17 18 if player { // I am the player, maximize the results 19 let sum = piles[i...x].reduce(0,+) 20 result = max(result, sum + _stoneGameII(piles, x+1, max(m, x - i + 1), !player, &hash)) 21 } 22 else { // I am the opponent, minimize the results 23 // Note we don't do "sum + _stoneGame" because we are 24 // only interested in player's result (number of stones) 25 result = min(result, _stoneGameII(piles, x+1, max(m, x - i + 1), !player, &hash)) 26 } 27 28 } 29 30 hash[key] = result 31 return result 32 } 33 } 34 35 struct Key: Hashable { 36 let i: Int 37 let m: Int 38 let player: Bool 39 40 init(_ i: Int, _ m: Int, _ player: Bool) { 41 self.i = i 42 self.m = m 43 self.player = player 44 } 45 }