【学习】博弈游戏

博弈问题

所讨论的博弈问题满足以下条件:

  1. 玩家只有两个人,轮流做出决策,且操作公平。
  2. 游戏的状态集有限,保证游戏在有限步后结束.
  3. 博弈双方都使用最优决策。

一个游戏有两个状态,我们称为必胜态和必败态,他们的关系:

  • 必胜态表示,从当前状态可以转移到一个必败态。
  • 必败态表示,从当前状态无法转移到一个必败态。

也就是说,一个状态不是必胜态,就是必败态。

知识点

SG函数

SG[x]=mex{SG[y]}

其中 y x所有的后继状态(通过操作改变当前状态为后继状态), mex 是最小的没有出现的连续自然数。

游戏的和

游戏 x1,x2,...,xn 的和为 x ,且x={x1,x2,...,xn}
理解为 x 是由x1,x2,...,xn构成的新游戏。

SG定理

如果一个游戏的所有子游戏相互独立(即一个子游戏的操作不会影响其他的子游戏),那么

SG[x]=SG[x1] xor SG[x2] xor ... xor SG[xn]

文字表述为,一些游戏的和的 SG 函数等于各个游戏 SG 函数的亦或和。

题目

BZOJ 2463 [中山市选2009]谁能赢呢?

思路:

可以证明,偶数的棋盘一定会被 1×2 的牌覆盖,奇数的棋盘一定可以被 1×2 的牌覆盖多出一个,所以说偶数的棋盘先手必胜,因为它只要走牌的后一个点一定可以赢,反之,奇数的棋盘先手必败。

代码:2463.cpp

BZOJ 1115 [POI2009]石子游戏

思路:

差分以后,就是经典的阶梯 Nim 取石子的模型,后面的端点。

代码:1115.cpp

BZOJ 4202 石子游戏

思路:

类似于阶梯 Nim 游戏,对于一个点为根来说,所有深度与其的差是偶数的点是无效的,因为当 A 做了这个操作以后,另一方B可以马上把 A 移动的石子再向上移动,奇数深度的点保持原来的状态。
动态加点需要link cut tree的支持,所以我们建立两颗 lct 把深度的奇偶分开维护,修改操作相当于给一个点到根的路径上的亦或和再抑或一个数,加点相当于在两颗 lct 中都新 link 一个点。附:LCT学习笔记
现在还有最多取 m 个的限制,可以从SG值的角度来考虑,前 m+1 个的 SG 值,是从 0m 的,但是第 m+2 SG 就无法选择第 1 SG了,取 mex 后他的 SG 值就是 0 ,所以不难发现,SG值表示的数量,是关于模 m+1 同余的。
换种角度看, m+1 是一个特殊的取值,这个值一次一定去不到,两次一定可以取完,所以说大于 m+1 的点,先手进行一次取值,后手可以紧跟着再 %m+1 的地方移动一次,便到前面模 m+1 同余的一样的地方去,这样的操作是没有意义的,所以说可以把权值 %(m+1) ,直接按上面的步骤做完即可。

代码:4202.cpp

BZOJ 4347 [POI2016]Nim z utrudnieniem

思路:

如果再取走之后,剩余的石子堆的疑异或和为 0 ,那么当前的选择就是一种合法的方案。
所以问题转换为求异或和为K的取值的方案数,其中 K 是所有权值的异或和。
状态:f[i][j][k]表示前 i 堆石头,现在取得堆数modd=j,异或和是 k 的方案数。
转移:f[i][j][k]=f[i1][j][k]+f[i1][(j1)mod d][k xor a[i]]
如果我们对 a 数组进行排序,那么每次异或和的最大值是2×a[i]
这样算下来,总的时间复杂度是 O(md) 的。
但是这个题的空间限制是 64MB ,只滚动第一维还是不够的,所以可以直接像背包那样,倒着转移,直接省去第一维,但是 0 需要从d1转移, d1 的状态改变后,就无法转移了,所以用一个辅助数组,先把 0 转移完,然后就可以了去掉第一维了。

代码:4347.cpp

BZOJ 4600 [Sdoi2016]硬币游戏

思路:

代码:4600.cpp

BZOJ 4134 ljw和lzr的hack比赛

思路:

首先划子游戏,拔一颗子树看成一个子游戏,显然,子游戏之间是互相独立的。
一个决策的状态值是以这个点到跟的路径上的所有点的非本链上的孩子为根的子游戏的异或和。
子树的SG值是子树内所有决策状态值的 mex
所以我们用二进制 Trie 来维护异或和与 mex 操作, Trie 的节点记录当前的子树内已有的点的个数。每一棵树记录一个永久化的标记,标记代表对整棵树的异或。
对原树进行 dfs ,所有的 Trie 进行启发式合并,对于最大树的修改,直接打标记,其他树的元素直接全部插入到大树当中。
统计答案时,记录当前点的所有子树的异或和,向下 dfs 的子树,把子树对应的异或消掉,继续向下搜。

代码:4134.cpp
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值