'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],因为只有一个硬币。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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,同理。

-------------end of file thanks for reading-------------
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值