LC 1872. 石子游戏 VIII
https://leetcode-cn.com/problems/stone-game-viii/
还是动态规划,还是要讲究计算顺序,才能得到子问题的最优解。
这题如果上来就想"在ith取石子的话,alice-bob的值最大可以是多少”,这种动态规划方法就是O(n^2), 显然是会超时的。这似乎是从后向前的思路。
从前向后的思路是,dp[i] 表示 "当前人A(可以是alice/bob)在这个位置开始取石子, A-B的最大差值是多少"
- 如果A取了ith的石子的话,那么获得了 prefix[i] 的分数,剩下就是 -dp[i+1] 的分数了。
- 如果A没有在ith取石子的话,那么就是 dp[i+1]
- 所以 dp[i] = max(prefix[i] - dp[i+1], dp[i+1])
- 最终值是 dp[1]. 因为alice开始必须要取1个石子
这个推导公式继续往下的话,可以去掉数组只留下2个变量
class Solution:
def stoneGameVIII(self, stones: List[int]) -> int:
n = len(stones)
acc = [0] * (n + 1)
for i in range(n):
acc[i + 1] = stones[i] + acc[i]
# 状态方程是dp[i]表示从i开始选择,alice-bob的最大差值
# alice不选择ith的话,那么dp[i] = dp[i+1]
# 如果选择ith的话,那么alice获得acc[i+1] value,
# 接下来就是bob取,所以dp[i] = acc[i+1] - dp[i+1]
dp = [0] * n
dp[n - 1] = acc[n]
# dp[i] = max(dp[i+1], acc[i+1] - dp[i+1])
for i in reversed(range(1, n-1)):
dp[i] = max(dp[i+1], acc[i+1] - dp[i+1])
# have to take one stone.
ans = dp[1]
return ans