0717更新
定义两个函数
分别是先手和后手
其中先手的含义是
假设我从数组的第i个到第j个之间 先手拿 我能拿到的最高分数
后手的意思是 我让对方从第i个到第j个之间 先手拿 之后我从剩下的再拿 此时我能拿到的最高分数
则 先手可以选择i和j,得分为nums[i]+后手(i+1,j)和nums[j]+后手(i,j-1)
希望自己拿的最多,则取max
对应上述两种情况,后手的结果分别是
先手(i+1,j)和先手(i,j+1)
由于先手一定希望后手得分少,故后手只能在上面两个值中取min
class Solution:
def __init__(self):
self.dicta = {}
def PredictTheWinner(self, nums: List[int]) -> bool:
return True if self.firsthand(0,len(nums)-1,nums)>=self.secondhand(0,len(nums)-1,nums) else False
def firsthand(self,i,j,nums):
if (i,j) in self.dicta:
return self.dicta[(i,j)]
if i==j:
self.dicta[(i,i)] = nums[i]
return nums[i]
else:
tempres = max(nums[i]+self.secondhand(i+1,j,nums),nums[j]+self.secondhand(i,j-1,nums))
self.dicta[(i,j)] = tempres
return tempres
def secondhand(self,i,j,nums):
if i == j:
return 0
else:
return min(self.firsthand(i+1,j,nums),self.firsthand(i,j-1,nums))
思路:
此题难点在于如何定义动态规划的子问题
我们定义dp[i][j]为,当前从[i,j](注意 闭区间)拿的选手若想赢,则要比对方多多少分
于是
若i=j
则 当前选手只能拿一个 则dp[i][i+1] = a[i]
若i +1= j
则当前选手只能从首尾选一个
则选更大的那个(相等则随便选 因为此时是先手赢)
dp[i][i+1] = max(a[i],a[i+1])
考虑三个的情况 即i + 2 == j
则当前选手可以从因为当前选手只能从A[0]或者A[-1]开始拿
则dp[i][i+2] = max(a[0]-dp[i+1][i+2],a[-1]-dp[i][i+1])
推广至一般情况
dp[i][j] = max(a[i]-dp[i + 1][j],a[j]-dplist[i][j - 1])
class Solution:
def PredictTheWinner(self, nums: List[int]) -> bool:
length = len(nums)
dplist = []
index = 0
while index < length:
iters = length - index
for i in range(iters):
if index == 0:
templist = [0 for _ in range(length)]
templist[i] = nums[i]
dplist.append(templist)
else:
dplist[i][i+index] = max(nums[i]-dplist[i + 1][i+index],nums[i+index]-dplist[i][i+index - 1])
index += 1
return True if dplist[0][length-1] >= 0 else False