LintCode 395: First Will Win 2

题目描述

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

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

样例

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

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

Sat Feb 26 2017

思路

一般这种博弈的题目都是假设双方足够聪明,能够用最优的策略取得胜利的,看似很麻烦,实际上却简化了问题,因为这样的话每一个状态都确定了。

看起来很像动态规划问题,那么就试试写状态转移方程吧。

设硬币数为 \(n\),令 \(dp[i]\) 为从 \(i\) 到 \(n - 1\) 能获得的最大价值。

显然:

\[dp[n - 1] = values[n - 1]
\]

\[dp[n - 2] = values[n - 1] + values[n - 2]$$ <p align="center">(还剩下两个硬币当然要全部拿完了)</p>
$$dp[n - 3] = values[n - 2] + values[n - 3]$$ <p align="center">(还剩下三个硬币当然要拿两个了)</p>

对于一般情况:

\]

dp[i]\,=\,{\rm max}
\begin{cases}
values[i]\,+\,{\rm min}\{dp[i + 2],\,dp[i + 3]\}, & \text{若本轮拿一个硬币} \\
values[i]\,+\,values[i + 1]\,+\,{\rm min}\{dp[i + 3],\,dp[i + 4]\}, & \text{若本轮拿两个硬币}
\end{cases}

\[
外层的 ${\rm max}$ 表示“我”要选择一个利于自身的方案:到底是拿一个还是两个。

内层的 ${\rm min}$ 表示对手要选择一个不利于“我”的方案。

最后只要看 $dp[0]$ 是否超过硬币总价值的 $1/2$ 即可。

有一个小细节需要注意一下,就是 $dp[n - 4]$ 的情况,如此时拿两个硬笔,那么剩下的两个肯定对手肯定会全都拿了,不会再去权衡博弈了。

### **代码**

```C++
// 硬币排成线 II
bool firstWillWin(vector<int> &values)
{
int n = values.size();
if (n <= 2) return true;
vector<int> dp(n);
dp[n - 1] = values[n - 1];
dp[n - 2] = values[n - 2] + values[n - 1];
dp[n - 3] = values[n - 3] + values[n - 2];
int sum = dp[n - 1] + dp[n - 3];
for (int i = n - 4; i >= 0; --i)
{
int get_one = values[i] + min(dp[i + 2], dp[i + 3]);
int get_two = values[i] + values[i + 1];
if (i != n - 4) get_two += min(dp[i + 3], dp[i + 4]);
dp[i] = max(get_one, get_two);
sum += values[i];
}
return dp[0] > sum / 2;
}
```\]

LintCode 395: First Will Win 2的更多相关文章

  1. LintCode 394: First Will Win

    LintCode 394: First Will Win 题目描述 有n个硬币排成一条线.两个参赛者轮流从右边依次拿走1或2个硬币,直到没有硬币为止.拿到最后一枚硬币的人获胜. 请判定 第一个玩家 是 ...

  2. [LintCode] 395. Coins in a Line 2_Medium tag: Dynamic Programming, 博弈

    Description There are n coins with different value in a line. Two players take turns to take one or ...

  3. lintcode 394. Coins in a Line 、leetcode 292. Nim Game 、lintcode 395. Coins in a Line II

    变型:如果是最后拿走所有石子那个人输,则f[0] = true 394. Coins in a Line dp[n]表示n个石子,先手的人,是必胜还是必输.拿1个石子,2个石子之后都是必胜,则当前必败 ...

  4. [LeetCode] 877. Stone Game == [LintCode] 396. Coins in a Line 3_hard tag: 区间Dynamic Programming, 博弈

    Alex and Lee play a game with piles of stones.  There are an even number of piles arranged in a row, ...

  5. [LeetCode] All questions numbers conclusion 所有题目题号

    Note: 后面数字n表明刷的第n + 1遍, 如果题目有**, 表明有待总结 Conclusion questions: [LeetCode] questions conclustion_BFS, ...

  6. [LeetCode] questions conclusion_ Dynamic Programming

    Questions: [LeetCode] 198. House Robber _Easy tag: Dynamic Programming [LeetCode] 221. Maximal Squar ...

  7. [LintCode]——目录

    Yet Another Source Code for LintCode Current Status : 232AC / 289ALL in Language C++, Up to date (20 ...

  8. leetcode & lintcode for bug-free

    刷题备忘录,for bug-free leetcode 396. Rotate Function 题意: Given an array of integers A and let n to be it ...

  9. leetcode & lintcode 题解

    刷题备忘录,for bug-free 招行面试题--求无序数组最长连续序列的长度,这里连续指的是值连续--间隔为1,并不是数值的位置连续 问题: 给出一个未排序的整数数组,找出最长的连续元素序列的长度 ...

随机推荐

  1. Rsyslog的模板template详解

    一. Template功能 根据用户需求指定任意格式 动态生成文件名 每个输出都使用了一些模板,包括针对文件的,针对用户消息等 备注: 旧版本:$template 新版本:template() V6之 ...

  2. lintcode-424-逆波兰表达式求值

    424-逆波兰表达式求值 求逆波兰表达式的值. 在逆波兰表达法中,其有效的运算符号包括 +, -, *, / .每个运算对象可以是整数,也可以是另一个逆波兰计数表达. 样例 ["2" ...

  3. [图算法] 1003. Emergency (25)

    As an emergency rescue team leader of a city, you are given a special map of your country. The map s ...

  4. 通过一台服务器ssh多台主机远程修改网卡ip

    在多台服务器环境下,更改所有的ip地址,网关,一台一台的登录修改显得复杂繁琐.   知识点: 参考#https://www.cnblogs.com/youngerger/p/9104144.html ...

  5. 【BioCode】读文件夹以发现缺失文件

    代码说明: 使用单个蛋白质的txt计算PSSM生成的结果为单个的PSSM文件. 但是由于一些原因(如蛋白质序列过长),会导致一些蛋白质txt文件无法计算出pssm,为了找到这些没有计算出pssm的蛋白 ...

  6. 这些天php面试的总结

    面试总结 记录一些本人在面试中遇到的觉得有些掌握不好的面试题,下面的答案都是本人回答的,如果哪里不对的话,希望各位能够指出. 1.Git fetch和git pull的区别 Git fetch相当于从 ...

  7. 动态Lambda表达式打印HelloWorld

    最近在用C#与数据库打交道.开发过程中采用了ORM模型(以前是纯sql玩法,复杂的逻辑用存储过程做). 为了能通过配置文件动态地查询字段,也就是说需要能这样写: db.AsQuery<T> ...

  8. Codeforces 618D Hamiltonian Spanning Tree(树的最小路径覆盖)

    题意:给出一张完全图,所有的边的边权都是 y,现在给出图的一个生成树,将生成树上的边的边权改为 x,求一条距离最短的哈密顿路径. 先考虑x>=y的情况,那么应该尽量不走生成树上的边,如果生成树上 ...

  9. bzoj4184shallot

    题意 给出一个初始为空的数字集合,每次添加一个数字/删除一个存在的数字,然后输出选出一些数进行异或能够得到的最大数值.操作次数<=500000,数字大小<2^31 分析 看上去我们只要写一 ...

  10. 【Java】Java CSV操作代码

    CSV是逗号分隔文件(Comma Separated Values)的首字母英文缩写,是一种用来存储数据的纯文本格式,通常用于电子表格或数据库软件.在 CSV文件中,数据“栏”以逗号分隔,可允许程序通 ...