'lintcode 硬币排成线2'

描述

有 n 个不同价值的硬币排成一条线。两个参赛者轮流从 左边 依次拿走 1 或 2 个硬币,直到没有硬币为止。计算两个人分别拿到的硬币总价值,价值高的人获胜。

请判定 先手玩家 必胜还是必败?

若必胜, 返回 true, 否则返回 false.

样例

样例 1:

输入: [1, 2, 2]
输出: true
解释: 先手玩家直接拿走两颗硬币即可.
样例 2:

输入: [1, 2, 4]
输出: false
解释: 无论先手拿一个还是两个, 后手可以拿完, 然后总价值更高.

思路

设dpi表示从i到n-1处,先手比后手多拿的分数。那么要求的就是dp0的正负。
因为只可以拿1个或者2个,所以最后的2个dpn-1 = values[n-1], dpn-2 = values[n-1]+values[n-2].
对于任意的dpi,也是只有2个取法:
拿1个values[i]时,先手获得了values[i],但是对于剩下的,他失去了先手,对面的先手获得了dpi+1,所以他比对面多values[i]-dpi+1
拿2个,values[i]和values[i+1]时,先手获得了values[i]+values[i+1],对面的先手可以获得dpi+2,所以此时先手比对面多values[i]+values[i+2]-dpi+2
最终可以从n-3计算到0,得到正负。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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 <= 1) return true;
vector<int> dp;
dp.resize(n,0);
dp[n-1] = values[n-1];
dp[n-2] = values[n-1] + values[n-2];
for (int i = n-3; i >= 0; i--) {
dp[i] = max(values[i] - dp[i+1], values[i]+values[i+1]-dp[i+2]);
}
return dp[0] > 0;
}
};
-------------end of file thanks for reading-------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值