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. 团队作业4——第一次项目冲刺(Alpha版本)第二次

    一.会议内容 各人进行下一步工作 发现沟通流程问题并解决 二.各人工作 成员 计划任务 遇见难题 贡献比 塗家瑜(组长) 后端逻辑处理 无 1 张新磊 数据库搭建 无 1 姚燕彬 测试计划编写 无 1 ...

  2. erlang中检查内存泄露

    最近项目内存占用过多,检查一下erlang的内存使用情况. 1. 通过etop可以很方便得出erlang内存使用的情况 spawn(fun() -> etop:start([{output, t ...

  3. spring-test与junit

    1.添加依赖 spring-test junit spring-context(自动添加依赖其他所需的spring依赖包) 2.在class前添加以下注解,用于配置xml文件的位置 @RunWith( ...

  4. css选择器和新增UI样式总结

    经过两天的学习,初步对css3选择器和新增UI样式有了进一步的理解.

  5. python/django将mysql查询结果转换为字典组

    使用python查询mysql数据库的时候,默认查询结果没有返回表字段名称,不方便使用.为了方便使用一般会选择将查询结果加上字段名称以字典组的方式返回查询结果. 实现如下: def dict_fetc ...

  6. java 基础 --Collection(Map)

    Map是不是集合?哈哈哈 java编程思想>的第11章,第216页,正数第13行,中原文:“……其中基本的类型是LIst.Set.Queue和Map.这些对象类型也称为集合类,但由于Java类库 ...

  7. 【.Net】C#获取Windows系统特殊文件夹的路径

    系统特殊文件夹是包含公共信息的文件夹,如“Program Files”.“Programs”.“System”或“Startup”.特殊文件夹在默认情况下由系统设置,或者由用户在安装 Windows ...

  8. HDU4678_Mine

    很有意思,很好的题目. 这样的,一个n*m的扫雷地图,告诉你哪些地方是有雷的.一个人如果点在了空白处,那么与其相邻的(八个方向)的数字以及空白都会递归地显示出来,如果点在数字上面,那么就只会显示这一个 ...

  9. liunx vim常用操作命令

    vim常用操作命令 vim abc // 打开该文件,或者新建文件 vim +3 abc // 打开文件并跳转到第三行 vim +/hello //打开文件并跳转到第一次出现hello的位置 vim ...

  10. [BZOJ2432][Noi2011]兔农 矩阵乘法+exgcd

    2432: [Noi2011]兔农 Time Limit: 10 Sec  Memory Limit: 256 MB Description 农夫栋栋近年收入不景气,正在他发愁如何能多赚点钱时,他听到 ...