lintcode 硬币排成线3

lintcode 硬币排成线3

描述

有 n 个硬币排成一条线,每一枚硬币有不同的价值。两个参赛者轮流从任意一边取一枚硬币,知道没有硬币为止。计算拿到的硬币总价值,价值最高的获胜。

请判定 第一个玩家 是输还是赢?

样例

给定数组 A = [3,2,2], 返回 true.

给定数组 A = [1,2,4], 返回 true.

给定数组 A = [1,20,4], 返回 false.

挑战

Follow Up Question:

If n is even. Is there any hacky algorithm that can decide whether first player will win or lose in O(1) memory and O(n) time?

思路

因为不确定从左边拿还是右边拿,所以设置一个二维数组dp[i][j]来表示从i到j这个区间,先手能比后手多拿的分数。
对于某一时刻的状态i,j,只有两个拿硬币的方法,一个是从左,一个是从右,选取其中的最大值,也就是
dp[i][j] = max(values[i]-dp[i+1][j], values[j]-dp[i][j-1])
对于初始状态,dp[i][i] = values[i],因为只有一个硬币。

代码

class Solution {
public:
    /**
     * @param values: a vector of integers
     * @return: a boolean which equals to true if the first player will win
     */
    bool firstWillWin(vector<int> &values) {
        // write your code here
        int n = values.size();
        if (n <= 2) return true;
        vector<vector<int>> dp;
        dp.resize(n, vector<int>(n));
        
        for (int i = 0; i < n; i++)
            dp[i][i] = values[i];
            
        for (int i = n-2; i >= 0; i--)
            for (int j = i+1; j < n; j++)
                dp[i][j] = max(values[i] - dp[i+1][j], values[j]-dp[i][j-1]);
        
        return dp[0][n-1] > 0;
    }
};

follow up

如果n是一个偶数,是否可以在On的时间复杂度和O1的空间复杂度内判断出先手的胜负?

n为偶数时,先手是必胜的。

n为偶数时,分数为values(0)~values(n-1)
奇数位置的和为sum1,偶数位置的和为sum2,sum1和sum2的大小是可以提前预知的
对于先手来说,假如sum1较大,那么他可以决定自己拿的全是奇数位置的硬币,从而必胜。
举个例子:六个硬币 a b c d e f a+c+e > b+d+f
先手拿a 此时后手只能拿bf,如果拿了b,先手再拿c,此时后手无论拿d或者f,e都是先手的,必胜
如果后手拿的f,同理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值