zoukankan      html  css  js  c++  java
  • 【笔记】简单博弈

    前言

    大半年前写的东西了,自己真的在走下坡路

    例题

    A , B进行游戏。A先开始,轮流将n减去{2,3,4,5,6}中的一个数,谁最后无法进行减法了,就输了。
    给定n。A,B都采用最优策略,问A是否会赢。

    状态

    设f[i]表示当前的数是i的时候,对于当前的先手来说是否会赢
    f[i]=true,则赢
    f[i]=false,则输

    转移

    当先手A操作一次后,问题转移为了对于当前先手B,对(n-i)进行操作

    必胜转移到必败,必败转移到必胜

    就是说
    从f[i]转移到的所有状态f[i-2],f[i-3]..f[i-6]如果都是必胜态,那么f[i]则为必败态
    从f[i]转移到的所有状态f[i-2],f[i-3]..f[i-6]如果都是必败态,那么f[i]则为必胜态

    初始化

    f[0]和f[1]对于先手来说必败
    f[0]=false,f[1]=false
    f[2]则对于先手来说必胜,f[2]=true

    碎碎念

    前几天上数学课的时候老师讲了一个类似的题,当时想到了DP。

    高级

    当n%8=1或0时,必败。否则必胜

    博弈DP的特征

    博弈DP解决的是两人轮流操作,且没有平局的 #两人博弈游戏#
    写代码的话一般是#人人为我#类型,即用其他状态向自己转移
    更一般的,博弈没有固定搜索顺序,习惯用记忆化搜索

    problem1【第一类,两人博弈类型】

    状态

    f[i][j]表示当前手上数字为i,上一个减去的数是j的时候是必胜还是必败

    转移

    f[i][j]转移到f[i-r][1~r],其中1<=r<=k*j

    复杂度

    O(n^3)
    没有代码

    problem2-1【第二类,组合两人博弈类型】

    A,B两人游戏,现在有a1,a2,...an共n个数, 轮流操作,每次可以对任意一个数操作,最后谁无法操作谁就输了。操作为将这个数减去{1,2,3,4,5,6}中的一个。

    范围:n<=(10^5),a_i<=(10^5)

    分析

    相当于有n个#二人博弈问题#,称之为#组合二人博弈问题#

    状态

    初始蒟蒻
    设计一个n维的f[1][2][3]...[n],表示当前态
    这玩意肯定不行,所以要用sg

    mex运算

    设S 表示一个非负整数集合。定义mex(S)为求出不属于集合S 的最小非负整数的运算。即:
    mex(S) = min{x|x(in) N, x$ otinS}, 比如mex{0,2,3} = 1

    sg函数(Sprague-Grundy 是两个人的名字)

    sg[i]表示的是数字i这个状态的sg值
    sg值:取出所有能转移到的sg值的前继状态集合{sg[1],sg[i-2]...sg[i-6]},则i的sg函数的值为这个集合的mex运算结果,即sg=mex{sg[1],sg[i-2]...sg[i-6]}

    必败态的sg为0,必胜态的sg值为非零

    对于这个题,sg[0]必败,所以s[0] = 0,s[1]的前继状态的集合为{s[0]},所以sg[1] = 1
    sg[2]的前继状态集合为{sg[0] = 0,sg[1] = 1},sg[2] = 2
    sg[3]的前继状态集合为{sg[0] = 0,sg[1] = 1,sg[2] = 2},sg[3] = 3
    sg[4] = 4,sg[5] = 5,sg[6] = 6
    sg[7]的状态集合为{sg[1] = 1, sg[2] = 2, sg[3] = 3,sg[4] = 4, sg[5] = 5, sg[6] = 6},sg[7] = 0
    sg[8] = 1,sg[9] = 2
    事实上,对于sg[8]和sg[9],先手必须把状态转移到sg[7],让下一个人必败

    对于这个题,有sg值就可以不用n维了吗?不行。他还是这个样子:
    sg[a1][a2]...[an]

    sg定理

    n个游戏的sg值 等于 每个游戏的sg值异或起来
    sg(a1,a2...an) = sg(a1) xor sg(a2) ... xor sg(an)

    所以我们分开讨论每个游戏,最后异或起来

    没有代码

    problem2-2——NIM游戏

    n <= (10^5) a_i <= $10^9¥

    problem3-1【第三类,可以转移到组合博弈】

    n+1堆石子,最左边一堆石头有2012个,两个人分别进行操作。一次操作可以选取两堆不同的石堆分别增加或减少一个石子(一加一减,或给已经不剩石子的堆加一个都是允许的)。为了保证游戏会在有限步内结束,规定所选的两堆中右边的那一堆一定要包含奇数个石子,无路可走者输.问先手是否必胜?

    problem3-2

    problem3-3

    必败态

    除了最左边,每一堆都是偶数个石子,所以不讨论每一堆的实际个数,只讨论奇偶
    a1,a2...an等于0或1

    problem3-4

    不关心石子个数,只关心奇偶
    因为独立的是石子而不是石子队
    因为我们的游戏单位是石子,两个石子的sg值相互抵消为0,所以只关心奇偶
    NIM的游戏单位是石子堆

    状态

    sg[i]在第i堆的石子的sg值

    转移

    sg[i] = mex(sg[j]^sg[k])

  • 相关阅读:
    BEM(Block–Element-Modifier)
    http://element.eleme.io/#/zh-CN/component/quickstart
    Commit message 的写法规范。本文介绍Angular 规范(
    好的commit应该长啥样 https://github.com/torvalds/linux/pull/17#issuecomment-5654674
    代码管理
    if you have content fetched asynchronously on pages where SEO is important, SSR might be necessary
    Martin Fowler’s Active Record design pattern.
    The Zen of Python
    Introspection in Python How to spy on your Python objects Guide to Python introspection
    Object-Oriented Metrics: LCOM 内聚性的度量
  • 原文地址:https://www.cnblogs.com/ZhengkunJia/p/13795148.html
Copyright © 2011-2022 走看看