486.预测赢家

题目:

给定一个表示分数的非负整数数组。 玩家1从数组任意一端拿取一个分数,随后玩家2继续从剩余数组任意一端拿取分数,然后玩家1拿,……。每次一个玩家只能拿取一个分数,分数被拿取之后不再可取。直到没有剩余分数可取时游戏结束。最终获得分数总和最多的玩家获胜。
给定一个表示分数的数组,预测玩家1是否会成为赢家。你可以假设每个玩家的玩法都会使他的分数最大化。

思路:
第一反应可以用dp处理,一开始写不来,也是看了评论的思路才写出来。

首先是要知道,偶数情况,先手必胜,因为先手拥有选择奇偶数列的权力,只需要选择较大者即可(例如:奇数列较大,则先取第一个数,无论玩家2怎么选都只能选偶数列的数)。

然后是奇数情况,需要用到dp了,dp[i][j]的意义是nums[i]~~nums[j]数列玩家1的最优解。主要有以下几种情况

  1. i == j 时: dp[i][j]就为nums[i]。
  2. i == j - 1 时:dp[i][j]为nums[i] 和nums[j]差的绝对值。
  3. 其他情况时:dp[i][j]一共有两种取法,就是先取 i 还是先取 j 。如果先取 i , 则玩家2一定用nums[i + 1] ~~ nums[j] 的最优解,即dp[i + 1][j],那么dp[i][j]的值为nums[i] - dp[i + 1][j],另一种情况同理。

代码:

bool PredictTheWinner(int* nums, int numsSize)
{
    if (numsSize % 2 == 0)
        return true;
    int** dp = (int** )calloc(numsSize, sizeof(int*));
    for (int i = 0;i < numsSize;i ++)
    {
        dp[i] = (int* )calloc(numsSize, sizeof(int));
    }

    for (int i = numsSize - 1;i >= 0;i --)
    {
        dp[i][i] = nums[i];
        for (int j = i + 1;j < numsSize;j ++)
        {
            if (j - i == 1)
            {
                int temp = nums[i] - nums[j];
                dp[i][j] = temp > 0 ? temp : - temp;
            }
            else
            {
                int temp1 = nums[i] - dp[i + 1][j];
                int temp2 = nums[j] - dp[i][j - 1];
                dp[i][j] = temp1 > temp2 ? temp1 : temp2;
            }
        }
    }
    int ans = false;
    if (dp[0][numsSize - 1] >= 0)
        ans = true;
    free(dp);
    return ans;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Zccccccc_tz

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值