3895: 取石子

Time Limit: 1 Sec  Memory Limit: 512 MB
Submit: 263  Solved: 127
[Submit][Status][Discuss]

Description

Alice和Bob两个好朋含友又开始玩取石子了。游戏开始时,有N堆石子
排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选一个:
·从某堆石子中取走一个
·合并任意两堆石子
不能操作的人输。Alice想知道,她是否能有必胜策略。

Input

第一行输入T,表示数据组数。
对于每组测试数据,第一行读入N。
接下来N个正整数a1,a2…an,表示每堆石子的数量。

Output

对于每组测试数据,输出一行。
输出YES表示Alice有必胜策略,输出NO表示Alice没有必胜策略。

Sample Input

2
3
1 1 2
2
3 4
3
2 3 5

Sample Output

YES
NO
NO

HINT

100%的数据满足T<=100,  N<=50. ai<=1000

Source

Solution

结论+记忆化搜索

首先,手玩或者感受一下,很好发现:操作总数S=$\sum a_{i}+N-1.......(x>1)$

这样进一步发现,如果S为奇数,显然先手必胜

证明:

难以证明S为奇数先手必胜,考虑证明S为偶数先手必败;

首先如果只有一堆,为奇数,显然先手必胜;

1.如果先手选择合并两堆石子,那么每堆石子的个数依然大于1,x变为奇数.

2.如果先手选择从一堆石子数大于2的堆中拿走一枚石子,那么同上每堆石子个数依然大于1,x变为奇数。

3.如果先手选择从一堆石子数等于2的堆中拿走一枚石子,那么后手可以合并剩下的1枚石子到任意一个堆。那样x的奇偶性不变,每堆石子的个数依然大于

所以这样可以得到对于所有x>1的情况,那么考虑存在x=1的情况

可以分为4种情况考虑:

1.取走某个大小为1的堆中的石子.

2.将某个大小为1的堆和某个大小不为1的堆合并

3.合并两个大小为1的堆.

4.对大小不为1的堆进行合并或者取石子操作.

那么我们用OK[i][j]表示状态,表示仅有1颗石子的有i堆,多颗石子堆的总操作数为S

那么对于上述情况,显然可以利用记忆化搜索转移

考虑数据最大值并不大,所以可以通过所有数据。

Code

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<cmath>
using namespace std;
inline int read()
{
int w=; char ch=getchar();
while (ch<'' || ch>'') ch=getchar();
while (ch>='' && ch<='') w=w*+ch-'',ch=getchar();
return w;
}
#define MAXN 100
#define int register int
bool ok[][],visit[][];
inline bool DFS(int x,int y)
{
if (!x) return y&;
if (y==) return DFS(x+,);
if (visit[x][y]) return ok[x][y];
visit[x][y]=;
if (x>= && y && !DFS(x-,y+)) {ok[x][y]=; return ;}
if (x>= && !y && !DFS(x-,y+)) {ok[x][y]=; return ;}
if (x && y && !DFS(x-,y+)) {ok[x][y]=; return ;}
if (y && !DFS(x,y-)) {ok[x][y]=; return ;}
if (x && !DFS(x-,y)) {ok[x][y]=; return ;}
ok[x][y]=;
return ;
}
main()
{
int N,a[MAXN],T,sum;
T=read();
while (T--)
{
N=read();
bool flag=;
sum=;
for (int i=; i<=N; i++)
{
a[i]=read(),sum+=a[i];
if (a[i]==) flag=;
}
if (flag)
if ((sum+N-)&) puts("YES"); else puts("NO");
else
{
int x=,y=;
for (int i=; i<=N; i++)
if (a[i]==) x+=a[i]; else y+=a[i]+;
if (DFS(x,max(y-,))) puts("YES"); else puts("NO");
}
}
// return 0;
}

Sunshine学长的Day3T2....

测试的时候,手玩了好几组,发现了结论,于是随口和DCrusher大爷一说

被DCrusher大爷一顿教育

大爷教育我说,随便一个记搜就出来了,然后滚去用10分钟写了个记搜..

手残写错了一个地方,卡成了80.....BeiYu大爷标算卡成50...

DCrusher实力虐场Orz

【BZOJ-3895】取石子 记忆化搜索 + 博弈的更多相关文章

  1. BZOJ 3895: 取石子[SG函数 搜索]

    有N堆石子 ·从某堆石子中取走一个 ·合并任意两堆石子 不能操作的人输. 100%的数据满足T<=100,  N<=50. ai<=1000   容易发现基础操作数$d=\sum a ...

  2. HDU 4597 Play Game (记忆化搜索博弈DP)

    题意 给出2*n个数,分两列放置,每列n个,现在alice和bob两个人依次从任意一列的对头或队尾哪一个数,alice先拿,且两个人都想拿最多,问alice最后能拿到数字总和的最大值是多少. 思路 4 ...

  3. BZOJ.1024.[SCOI2009]生日快乐(记忆化搜索)

    题目链接 搜索,枚举切的n-1刀. 对于长n宽m要切x刀,可以划分为若干个 长n'宽m'要切x'刀 的子问题,对所有子问题的答案取max 对所有子问题的方案取min 就是当前状态答案. 这显然是会有很 ...

  4. bzoj 3895 取石子 —— 博弈论

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看了博客:https://blog.csdn.net/popoqqq/article/ ...

  5. bzoj 3895: 取石子

    $ \color{#0066ff}{ 题目描述 }$ Alice和Bob两个好朋含友又开始玩取石子了.游戏开始时,有N堆石子 排成一排,然后他们轮流操作(Alice先手),每次操作时从下面的规则中任选 ...

  6. bzoj 3895 取石子——博弈论

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3895 看题解:https://blog.csdn.net/popoqqq/article/d ...

  7. bzoj 1415 期望dp + 记忆化搜索

    思路:这个题看着感觉不能dp,其实是可以dp的,因为狼每次走两步,兔子每次走一步,每进行一轮以后,狼和兔子的距离 肯定是在接近的,没有相同的状态,dp之前预处理出来,每一步狼该往哪里走. #inclu ...

  8. HDU 4597 记忆化搜索

    ² 博弈取牌—记忆化搜索 题目描述: 有两副带有数字的牌,(数字>0)两人轮流取,取中了某张牌,自己的分数就加上牌上的数字,但只能从两端取,每人都会用最优的策略使得自己的分数最高.问A先取,他能 ...

  9. UVALive 6470 Chomp --记忆化搜索

    题意:给一个只有三行的方块阵(横向最多100个),然后p,q,r分别代表第1,2,3层的方格数,两人轮流去掉一个格子,此时这个格子的右上方都会被去掉,面临只剩最左下角的一个格子的状态的人输,问先手能否 ...

随机推荐

  1. SQL Server 安装 功能详解

    安装 SQL Server 功能     在“功能选择”页上,SQL Server 功能分为以下两个主要部分:实例功能和共享功能. “实例功能”表示为每个实例安装一次的组件,这样,您将具有它们的多个副 ...

  2. HDU 1166 敌兵布阵

    B - 敌兵布阵 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit Sta ...

  3. usb驱动开发13之设备生命线

    上一节勉勉强强把struct urb这个中心给说完,接着看那三个基本点. 第一个基本点,usb_alloc_urb函数,创建urb的专用函数,为一个urb申请内存并做初始化,在drviers/usb/ ...

  4. 利用Canvas进行绘制XY坐标系

    首先来一发图 绘制XY的坐标主要是利用Canvas setLeft和setBottom功能(Canvas内置坐标的功能) 1.首先WPF中的坐标系都是从左到右,从上到下的 即左上角位置(0,0)点,所 ...

  5. LINQ的高级应用

    ---恢复内容开始--- 本文不想罗列linq的通俗使用方法.因为很多博文都已经写得很详细了. 此处直接贴出源码,如果有需要的朋友可以参考,希望更多的朋友能够补充更多的linq的高级应用. 源码如下: ...

  6. HTTP 状态代码表示什么意思?

    HTTP 状态代码表示什么意思? 如果某项请求发送到您的服务器要求显示您网站上的某个网页,服务器将会返回 HTTP 状态码响应请求.此状态代码提供关于请求状态的信息,一些常见的状态代码为: 200 - ...

  7. Javascript DOM操作实例

          最近在学DOM,但是还是没有办法很好的记住API,想找些例子来练习,网上的例子将一个个DOM对象方法挨个举例,并没有集合在一起用,效果不尽人意.所以自己写一份实例,顺便巩固下学到的知识. ...

  8. canvas 2d 贴图技术实践

    最近在公司内部的技术协会论坛里闲逛的时候,无意中发现了一篇手淘前端大牛岑安两年前写的博文,讲述了canvas的2d贴图技术.看到后觉得相当神奇.于是就自己实现了一下.不过岑安前辈的那篇博文也只是大概讲 ...

  9. NDK开发之javaVM

    1.关于JNIEnv和JavaVM JNIEnv是一个与线程相关的变量,不同线程的JNIEnv彼此独立.JavaVM是虚拟机在JNI层的代表,在一个虚拟机进程中只有一个JavaVM,因此该进程的所有线 ...

  10. Word Excel 操作总结

    1.与office无关使用 Aspose.Cells.dll,Aspose.Words.dll 2.使用Microsoft.Office.Interop.Excel Microsoft.Office. ...