1. 程式人生 > 實用技巧 >395. 硬幣排成線 II

395. 硬幣排成線 II

395.硬幣排成線 II

中文English

n個不同價值的硬幣排成一條線。兩個參賽者輪流從左邊依次拿走 1 或 2 個硬幣,直到沒有硬幣為止。計算兩個人分別拿到的硬幣總價值,價值高的人獲勝。

請判定先手玩家必勝還是必敗?

若必勝, 返回true, 否則返回false.

樣例

樣例 1:

輸入: [1, 2, 2]
輸出: true
解釋: 先手玩家直接拿走兩顆硬幣即可.

樣例 2:

輸入: [1, 2, 4]
輸出: false
解釋: 無論先手拿一個還是兩個, 後手可以拿完, 然後總價值更高.
輸入測試資料(每行一個引數)如何理解測試資料?

解法一:動態規劃

class
Solution: """ @param values: a vector of integers @return: a boolean which equals to true if the first player will win """ def firstWillWin(self, values): # write your code here #動態規劃 #如果是len(values)<= 3的情況,則直接給出答案 #如果是len(valeus) > 3的情況,分情況,要麼先手拿一個,要麼拿兩個 length
= len(values) if (length <= 2): return True dp = [0 for _ in range(length + 1)] total = 0 #如果是<=3的話 #如果是隻拿最後一個的話,先手必拿 dp[length - 1] = values[length - 1] #如果是剩餘最後兩個的話,先手也必拿 dp[length - 2] = values[length - 1] + values[length - 2
] #如果是剩餘三個的話,那麼先手最優策略是拿前兩個,最後一個留給後手 dp[length - 3] = values[length - 2] + values[length - 3] total = sum(values[length - 3:]) #如果是大於3的話,分情況考慮 for i in range(length - 4, -1, -1): total += values[i] #先手要麼拿一個,要麼拿兩個,後手也是最優策略,所以後手也儘可能的多拿,min(dp[i + 2], dp[i + 3]) dp[i] = max(values[i] + min(dp[i + 2], dp[i + 3]), values[i] + values[i + 1] + min(dp[i + 3], dp[i + 4])) #最後比較兩者大小,肯定是先手拿,也就是第一個 return dp[0] > total - dp[0]