LeetCode-1406-DP博弈問題應用
1406. 石子游戲 III
Alice 和 Bob 用幾堆石子在做遊戲。幾堆石子排成一行,每堆石子都對應一個得分,由陣列 stoneValue 給出。
Alice 和 Bob 輪流取石子,Alice 總是先開始。在每個玩家的回合中,該玩家可以拿走剩下石子中的的前 1、2 或 3 堆石子 。比賽一直持續到所有石頭都被拿走。
每個玩家的最終得分為他所拿到的每堆石子的對應得分之和。每個玩家的初始分數都是 0 。比賽的目標是決出最高分,得分最高的選手將會贏得比賽,比賽也可能會出現平局。
假設 Alice 和 Bob 都採取 最優策略 。如果 Alice 贏了就返回 "Alice" ,Bob 贏了就返回 "Bob",平局(分數相同)返回 "Tie" 。
示例 1:
輸入:values = [1,2,3,7]
輸出:"Bob"
解釋:Alice 總是會輸,她的最佳選擇是拿走前三堆,得分變成 6 。但是 Bob 的得分為 7,Bob 獲勝。
示例 2:
輸入:values = [1,2,3,-9]
輸出:"Alice"
解釋:Alice 要想獲勝就必須在第一個回合拿走前三堆石子,給 Bob 留下負分。
如果 Alice 只拿走第一堆,那麼她的得分為 1,接下來 Bob 拿走第二、三堆,得分為 5 。之後 Alice 只能拿到分數 -9 的石子堆,輸掉比賽。
如果 Alice 拿走前兩堆,那麼她的得分為 3,接下來 Bob 拿走第三堆,得分為 3 。之後 Alice 只能拿到分數 -9 的石子堆,同樣會輸掉比賽。
示例 3:
輸入:values = [1,2,3,6]
輸出:"Tie"
解釋:Alice 無法贏得比賽。如果她決定選擇前三堆,她可以以平局結束比賽,否則她就會輸。
示例 4:
輸入:values = [1,2,3,-1,-2,-3,7]
輸出:"Alice"
示例 5:
輸入:values = [-1,-2,-3]
輸出:"Tie"
提示:
1 <= values.length <= 50000
-1000<= values[i] <= 1000
來源:力扣(LeetCode)
連結:https://leetcode-cn.com/problems/stone-game-iii
解析:
- 定義:dp[i]當前玩家從位置i走起所能獲取的最大相對分數,即score = Alice-Bob
- 初始化:dp[*]= min
- 公式:dp[i]=max(dp[i], sum(stoneValue[i: i + k]) - dp[i + k]),k in (1 ,2, 3)
- 結果:dp[0]
- 複雜度:O((n-k)*k)
sum(stoneValue[i: i + 1]) - dp[i + 1]),當前走i,對手從i+1走
sum(stoneValue[i: i + 2]) - dp[i + 2]),當前走到i+1,對手從i+2走
sum(stoneValue[i: i + 3]) - dp[i + 3]),當前走到i+2,對手從i+3走
還可以計算每個人的分數,如下計算公式:
程式碼如下:
import sys
def stoneGameIII(stoneValue) -> str:
n = len(stoneValue)
stoneValue += [0, 0, 0]
dp = [-sys.maxsize] * n + [0, 0, 0]
for i in range(n):
for k in (1, 2, 3):
dp[i] = max(dp[i], sum(stoneValue[i: i + k]) - dp[i + k])
return "Alice" if dp[0] > 0 else "Bob" if dp[0] < 0 else "Tie"