【LeetCode486】【递归/dp】每日一题day2

我好菜,题做得太少了,思维的东西不够。
这道题第一眼我以为是dp,但是它有两个人,好像不满足无后效性,之后又以为是博弈论,但是它又不像取石子有必败态。又觉得这道题数据范围才20,它肯定是想让我们暴搜,但是暴搜我不会写TvT
看了题解,可以递归也可以dp…

方法一:递归
就比较直观,但是要注意这里用turn将玩家二的得分记为负数,就不用再传一个变量了,之后比较大小的时候也要注意正数和负数的问题。

class Solution {
public:
    int predict(vector<int>& nums, int turn, int head, int tail)
    {
        if (head == tail) return nums[head] * turn;
        int headScore = nums[head] * turn + predict(nums, turn * (-1), head + 1, tail);
        int tailScore = nums[tail] * turn + predict(nums, turn * (-1), head, tail - 1);
        return max(headScore * turn, tailScore * turn) * turn;
    }
    
    bool PredictTheWinner(vector<int>& nums) {
        return predict(nums, 1, 0, nums.size() - 1) >= 0;
    }
};

方法二:dp
这种序列取两段的数的问题,感觉一般会用到区间[l, r],每个状态都可以表示为这样一个区间
dp[l][r]表示剩余的数是从第l个到第r个的时候,当前走棋的玩家与对面玩家的分差最大值。
dp[l][r] = max(nums[l] - dp[l + 1][r], nums[r] - dp[l][r - 1])
这个状态转移方程式里的减号是灵魂,用一个减号完成了换玩家。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值