xsy1436-括号游戏
题目
递归定义括号序列:
- 空串是括号序列
- (A)是一个括号序列,其中A为括号序列
- AB是一个括号序列,其中A,B均为括号序列
定义严格括号序列为形如(A)的括号序列,其中A为括号序列。
给出一个长度为\(n(n\le 10^3)\)的合法括号序列,两个人进行游戏,每次一个人取走一个严格括号序列,不能再取的算输,问先手必胜还是后手必胜。
分析
好题。严格括号序列可以看成一棵树。一个严格括号序列的每个左括号表示一个点深搜进入,右括号表示遍历完所有的子树了。一个不严格的括号序列可以看成一堆树,就是一个森林。这个游戏完全等价于在一个森林中轮流删除一个点及其子树。这是一个经典问题。
Green Hackenbush Game
砍树游戏是指,在一个有根树组成的森林中,两个玩家轮流砍掉树上的一条边,那条边连出去的子树都被砍掉。无法操作者输。
如何考察这个问题?首先考虑最简单的形式,所有的有根树都是一条链,那么这个问题就完全等价于一个Nim游戏,因为每一次都是在一棵树上的\(n\)个点中删去\(a\in [1,n]\)个点,相当于在许多堆石子中每次选一堆,取出任意多个。从SG函数的角度看,对于一条链,它的SG值其实就是链的长度。
接下来考虑如何把一颗分叉的树转化为链的形式。
Colon Principle
对于树上的一个分叉的节点,所有的分叉都是一条链,那么可以把这些分叉换成一条长度为它们异或和的链,新树与原树在游戏中等价。
有了这个性质,我们只要自下而上把所有的分叉换成链,到最后整棵树形成一条链,我们就得到整棵树的SG值了。
下面我们来证明这个性质。
有两颗随机的树\(H_1,H_2\),满足它们的SG函数值是相同的。现在有一棵树\(G\)和上面一个定点\(x\),用\(G_1\)表示把\(H_1\)接在\(G\)的\(x\)点上形成的树,\(G_2\)表示把\(H_2\)接在\(G\)的\(x\)点上形成的树。我们现在要证明的就是,这两棵树根节点的SG函数值是相同的。这其实就是在证明两棵树的根节点的SG值异或为0。由于多个子游戏拼成的大游戏的SG值就是每个子游戏的SG值异或起来,所以这个证明等价于把这两棵树放在一起做游戏,规则是每次砍掉任意一棵树的任意一条边,后手必胜。一种显然的后手必胜方法就是,对于不涉及到\(H\)内部的操作,后手模仿先手的操作,因为两棵树除了\(H\)的部分是完全一样的。对于涉及到\(H\)内部的操作,即只涉及子树内的操作,我们可以看成是\(H_1\)和\(H_2\)单独做游戏。由于\(H_1\)和\(H_2\)的SG函数值是一样的,所以这两颗树的单独游戏也是后手必胜的。这样整个游戏就是后手必胜的了,故结论成立。
非常巧妙的构造和证明!
代码
#include<cstdio>
#include<cctype>
#include<cstring>
using namespace std;
int read() {int x=0,f=1;char c=getchar();for (;!isdigit(c);c=getchar()) if (c=='-') f=-1;for (;isdigit(c);c=getchar()) x=x*10+c-'0';return x*f;
}
const int maxn=1e3+1;
char s[maxn];
int sta[maxn],top,n,tim=0,ck[maxn];
struct edge {int v,nxt;
} e[maxn<<1];
int h[maxn],tot=0,ans,f[maxn],all;
void add(int u,int v) {if (ck[u]!=tim) ck[u]=tim,h[u]=0;e[++tot]=(edge){v,h[u]};h[u]=tot;
}
void dfs(int x) {f[x]=0;if (ck[x]!=tim) h[x]=0;for (int i=h[x],v=e[i].v;i;i=e[i].nxt,v=e[i].v) dfs(v),f[x]^=f[v];++f[x];
}
int main() {#ifndef ONLINE_JUDGEfreopen("test.in","r",stdin);#endifint T=read();while (T--) {scanf("%s",s+1);n=strlen(s+1);top=ans=0;for (int i=1;i<=n;++i) {if (!top) {++tim,tot=all=0;sta[++top]=++all;continue;}if (s[i]=='(') {int u=sta[top];sta[++top]=++all;add(u,all);} else --top;if (!top) {dfs(1);ans^=f[1];}}puts(ans?"peipei":"iamcs");}return 0;
}
转载于:https://www.cnblogs.com/owenyu/p/6724634.html
xsy1436-括号游戏相关推荐
- 简评游戏人工智能相关的中文书(下)
赖勇浩(http://laiyonghao.com) 游戏开发中的人工智能 2006 年 9 月第一版 AI for Game Develpoers 应该算得上一本质量在中等偏上的书,可惜的是即使中文 ...
- 拇指接龙游戏升级记录03(升级MainScene.cpp)
MainScene是拇指接龙游戏的主游戏场景文件,拥有近5000行代码. 说实在的,实现自cocos2d-x 2.x版本向当下最新的3.8.1版本的升级过程,其中涉及的技术不是一下能够说明的.有些是形 ...
- LeetCode实战:Nim 游戏
背景 为什么你要加入一个技术团队? 如何加入 LSGO 软件技术团队? 我是如何组织"算法刻意练习活动"的? 为什么要求团队的学生们写技术Blog 题目英文 You are pla ...
- 用 Linux 命令玩一个有趣的数学游戏
在家玩流行的英国游戏节目 "Countdown" 中的数字游戏. 像许多人一样,我在大流行期间看了不少新的电视节目.我最近发现了一个英国的游戏节目,叫做 Countdown,参赛者 ...
- C语言经典小游戏---猜数字游戏 (包含C语言中如何实现随机数的生成)
题目描述:输入1-100之间的数字,进行猜数字游戏,猜大猜小有提示,直至才对为止,游戏可以重复游玩. 算法思路: 1.用void函数分别写出菜单程序与游戏进程程序. 2.用switch-case-de ...
- noj数据结构稀疏矩阵的加法十字链表_一个算法毁了一款好游戏?算法和数据结构到底有多重要?...
来源 | 异步 | 文末赠书 前段时间大火的国产游戏--<太吾绘卷>,由于创新的玩法和精良的制作一度广受好评,然而随着玩家游戏的深入和时长的积累,发现该游戏在玩的过程中游戏外的问题很多很多 ...
- 用 Redis 搞定游戏中的实时排行榜,附源码!
原文:segmentfault.com/a/1190000019139010 1. 前言 前段时间刚为项目(手游)实现了一个实时排行榜功能, 主要特性: 实时全服排名 可查询单个玩家排名 支持双维排序 ...
- 【BZOJ 1095】 1095: [ZJOI2007]Hide 捉迷藏 (括号序列+线段树)
1095: [ZJOI2007]Hide 捉迷藏 Description 捉迷藏 Jiajia和Wind是一对恩爱的夫妻,并且他们有很多孩子.某天,Jiajia.Wind和孩子们决定在家里玩 捉迷藏游 ...
- python编写赛车游戏单机版_使用Keras和DDPG玩赛车游戏(自动驾驶)
为什么选择TORCS游戏 <The Open Racing Car Simulator>(TORCS)是一款开源3D赛车模拟游戏 看着AI学会开车是一件很酷的事 可视化并考察神经网络的学习 ...
- 《Android游戏开发详解》——第1章,第1.6节函数(在Java中称为“方法”更好)...
本节书摘来自异步社区<Android游戏开发详解>一书中的第1章,第1.6节函数(在Java中称为"方法"更好),作者 [美]Jonathan S. Harbour,更 ...
最新文章
- Xdebug的安装-(无错可执行版)
- list,set,map,数组间的相互转换
- 【博客话题】技术人生之三界修炼
- Nova如何统计节点硬件资源
- 为什么做软件类项目,会出现人多,事少,工作量大的情况?
- java trrows处理_java 19 -2 异常以及tr...catch()的方法处理异常
- morphological antialiasing
- 管理感悟:需要什么样的技术文档
- java贪吃蛇总结报告_java贪吃蛇开发总结
- java 命令 native2ascii_Java用native2ascii命令做unicode编码转换
- python画正切函数_在matplotlib中绘制tan
- java 动态统计报表_java统计图表FineReport制作动态图表
- 精选150道iOS面试题
- 服务器防火墙的作用是什么?如何设置?
- 使用Beep()函数发出指定音高 (一)
- codewars体验
- 汽车辅助驾驶系统中的图像处理算法
- HTML笔记(课堂笔记整合)
- 这是我见过最通俗易懂的MES与ERP介绍文章,带你剖析工业4.0!
- A problem has occurred and the system can‘t recover问题的解决