Leetcode刷题记录——486. 预测赢家

在这里插入图片描述

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值