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. 数学口袋精灵感受与BUG

    232朱杰 http://www.cnblogs.com/alfredzhu https://github.com/alfredzhu/ 组长,团队 230蔡京航 http://www.cnblogs ...

  2. 【beta】Scrum站立会议第3次....11.6

    小组名称:nice! 组长:李权 成员:于淼  刘芳芳韩媛媛 宫丽君 项目内容:约跑app(约吧) 时间:2016.11.6  12:00——12:30 地点:传媒西楼220室 本次对beta阶段的需 ...

  3. maven 实践 :管理依赖

    有人认为Maven是一个依赖管理工具,当然这种想法是错误的(确切的说Maven是一个项目管理工具,贯穿了整个项目生命周期,编译,测试,打包,发布...),但Maven给人造成这种错误的印象也是有原因的 ...

  4. 第98天:CSS3中transform变换详解

    transform变换详解 本文主要介绍变形transform. Transform字面上就是变形,改变的意思.在CSS3中transform主要包括以下几种:旋转rotate.扭曲skew.缩放sc ...

  5. HDU4258_Covered Walkway

    题目是一个很典型的斜率优化的题目.题意就不说了. 是这样的,对于双端优先队列,我们共有队首和队尾两个删除操作,来保证对于任意一个i,第一个元素都是最优的. 我们把dp的转移方程列出来就直达其状态为f[ ...

  6. luogu 1712 区间(线段树+尺取法)

    题意:给出n个区间,求选择一些区间,使得一个点被覆盖的次数超过m次,最小的花费.花费指的是选择的区间中最大长度减去最小长度. 坐标值这么大,n比较小,显然需要离散化,需要一个技巧,把区间转化为半开半闭 ...

  7. 【uoj#22】[UR #1]外星人 组合数学+dp

    题目描述 给你一个长度为 $n$ 的序列 $\{a_i\}$ 和一个数 $x$ ,对于任意一个 $1\sim n$ 的排列 $\{p_i\}$ ,从 $1$ 到 $n$ 依次执行 $x=x\ \tex ...

  8. 【uoj#310】[UNR #2]黎明前的巧克力 FWT

    题目描述 给出 $n$ 个数,从中选出两个互不相交的集合,使得第一个集合与第二个集合内的数的异或和相等.求总方案数. 输入 第一行一个正整数 $n$ ,表示巧克力的个数.第二行 $n$ 个整数 $a_ ...

  9. Shell脚本修改Nginx upstream配置文件

    #!/bin/bash ##################################################### # Name: change_nginx_upstream_conf ...

  10. C 类网络的子网快速划分

    CIDR ( Classless Inter-Domain Routing ,无类域间路由选择) 进行子网划分的方法有很多,最适合你的方式就是正确的方式.在 C 类地址中,只有 8 位用于定义主机.注 ...