zoukankan      html  css  js  c++  java
  • 博弈论学习笔记

    前言&引入

    很久之前就想开博弈论这个坑了,因为打比赛经常遇到博弈问题结论题,只能靠感觉来做,没有系统的学习过博弈论。

    前一周数学老师在一节数学课下课前提了一个好玩的游戏,顿时风靡全班。

    这个游戏是这样的:现在有 (30) 个数要报,两个人轮流报数,每次最多报 (2) 个数,最少报 (1) 个数,先报到 (30) 的人赢。

    数学老师找了几个人来玩 (因为她认为我破坏游戏平衡就把我ban掉了),每次都是她后手,而她每次都赢,于是许多同学开始试怎样报数必赢,许多同学发现了后手的必赢策略,只要对方报奇数则他报偶数,否则报奇数。那么为什么这个策略是必胜的呢?数学老师估计是忘了或者根本没打算讲,于是这个坑由我来填了!

    考虑上面那个必胜策略的证明其实很简单,因为后手每次都会取到 (3) 的倍数,而要取的数正是 (3) 的倍数,所以后手一定会取到 (30)

    Part1 问题的开始--你好,博弈论

    那么现在,让我们来考虑前言所提到的问题的一般情况:

    首先,我们给这个有趣的游戏建立一个模型,也就是把这个问题用数学语言描述出来:

    现在有 (n) 个石子要取,两个人轮流取石子,每次最多取 (m) 个石子,最少取 (1) 个石子,取走第 (n) 个石子的人赢得游戏。其中满足 (n,m > 0)。考虑两个人都足够聪明的情况下判断先手还是后手必胜,并解释必胜策略。

    (nleq m) 的时候先手必胜,因为先手可以第一次就把 (n) 个石子全取完。

    那么当 (n>m) 时呢?

    定义 (f(x)) 为从剩下 (x) 个石子时开始取是否必胜。如果必胜 (f(x)=1),称 (f(x)) 为必胜点,否则值为 (0),称 (f(x)) 为必败点。

    对于 (f(1),f(2),f(3)...f(m)) 肯定为 (1),因为 (f(1)) 是取 (1) 次可以取走 (n)(f(2))(2) 次取走 (n)...(f(m))(m) 次取走 (n)

    对于 (f(m+1)),它的值为 (0),因为走到这一步时,不管取几个石子都会走到 (f(1),f(2),f(3)...f(m)) 中的一个,这样就会让对方走到必胜点。也就是说剩下 ((m+1)) 个石子开始取的话一定是输的。由此可见,只能走到必胜点的点一定是必败点

    那么再来看 (f(m+2)),走到这一步时,肯定不能取 (2) 个及以上石子,因为这样会给对手必胜点,而取 (1) 个石子会给到对手必败点也就是 (f(m+1)),所以 (f(m+2)) 为必胜点,因为取走 (1) 个石子就可以让对方必败。类似的,(f(m+3),f(m+4)...f(2 imes m+1)) 都是必胜点,它们分别是取 (2,3...m) 个石子,把 (f(m+1)) 这个必败点给对手。由此可见,能走到必败点的点一定是必胜点

    我们把 (f(x))(x=1,2,3...n) 的顺序列一个表,发现是以长度为 ((m+1)) 的循环节在循环,每一个循环节里面,前 (m) 个点是必胜点,最后一个点是必败点,也就是说我们看 (1) 是必胜点还是必败点就能判定先手必胜还是先手必败(先手必败也就是后手必胜)。

    那么看先手是必胜点还是必败点只需要看先手先开始取的这个 (f(n)) 的取值,根据我们刚刚找到的规律,当 (n) 是在最后这个循环节的末尾时就是必败点,否则为必胜点。(n) 在循环节的末尾也就是 (n) 个石子可以表示为若干个长度为 ((m+1)) 的段,也就是 (n\%(m+1)=0) ((\%) 为取模运算,(x\% y) 就是 (x) 除以 (y) 的余数(这里为整除)),或者说 (n)((m+1)) 的倍数。

    综上所述,(n)((m+1)) 的倍数时后手必胜,否则先手必胜。

    那么必胜策略呢?如果不是必胜那么怎么取都无所谓反正一定会输,如果是后手必胜,那么先手取 (x) 个时,后手取 ((m+1-x)) 个,这样可以保证后手每次都是取到 ((m+1)) 的倍数,最终取到 (n) (因为 (n)((m+1)) 的倍数),如果是先手必胜,那么先手先取 (n\% (m+1)) 个石子,这样就相当于把 (n) 减去了 (n\% (m+1)),使得 (n)((m+1)) 的倍数,同时把先手扔给对方,后面的策略就和上面的后手必胜策略一样了。

    (Q.E.D.)

    其实这个必胜策略很好猜,直接从必胜策略证明先手必胜还是后手必胜的结论貌似很简单,但是笔者认为这仅仅满足充要性,不能满足必要性。而如果是上文所示的证明,是可以证明出必要性的。

    Part2 简单题选做--感受博弈论

    Codeforces 533C Board Game

    题目翻译

    小P和小V在一个平面直角坐标系上,小P初始在 ((x_p,y_p)),小V初始在 ((x_v,y_v))。小P和小V交替移动,由小P开始。

    每次小P可以从他所在的 ((x_p,y_p)) 移动到 ((x_p-1,y_p),(x_p,y_p-1)) 中的一个,小V可以从他所在的 ((x_v,y_v)) 移动到 ((x_v-1,y_v-1),(x_v,y_v-1),(x_v-1,y_v-1)) 中的一个,但是两个人要保证不能移动到对方的位置并且不能移动到坐标为负的地方,在一次移动中他们也可以选择留在原地不动,先到达 ((0,0)) 的人赢,给定 (x_p,y_p,x_v,y_v),在两人都足够聪明的情况下,求出游戏的胜者。((x_p,y_p,x_v,y_v)leq 10^5)

    Solution:

    1. (x_p+y_pleq max(x_v,y_v))

    此时小P必胜,因为小V不管选择怎么走,小P都可以选择一种走法使得这个不等式依然成立,到最后会有小P先到达 ((0,0))

    1. (x_pleq x_v,y_pleq y_v)

    此时小P必胜,和上面同理,小V不管选择怎么走,小P都可以选择一种走法使得这两个不等式依然成立,因为考虑到不可能同时满足 (x_p eq x_v,y_p eq y_v),所以小P只需要看横坐标还是纵坐标和小V相等了,就把哪个坐标 (-1),显然这样会使得小P走到 ((0,0))

    1. 其他情况

    实际上小P只有上面两种情况可以赢,但是笔者并不会证明

    考虑到不管小P怎样走,小V都可以选择一种走法使得上面两个条件都不成立,然而小P到 ((0,0)) 的最短路径就是 (x_p+y_p),小V到 ((0,0)) 的最短路径就是 (max(x_v,y_v)),既然不满足条件1,所以小V离原点更近,肯定是小V先到达原点即小V必胜。

    Code

    signed main() {
    	#define Pwin { puts("Polycarp"); return 0; }
    	#define Vwin { puts("Vasiliy"); return 0; }
    	int x1 = read(), y1 = read(), x2 = read(), y2 = read();
    	if(x1 + y1 <= Max(x2, y2)) Pwin;
    	if(x1 <= x2 && y1 <= y2) Pwin;
    	Vwin;
    }
    

    Reference

    待更...

    推荐阅读

    绝顶我为峰 简单食用的博弈论

    博弈论 - OI WiKi

  • 相关阅读:
    hdu 1171 Big Event in HDU (01背包)
    Codeforces 86C Genetic engineering (AC自己主动机+dp)
    ANDROID L——Material Design具体解释(动画篇)
    三层架构理论篇
    Linux下的tree命令 --Linux下文件夹树查看
    排序之冒泡排序、插入排序及希尔排序
    TRIZ系列-创新原理-9~11-预先反作用原理、预处理原理、预先防范原理
    Linux 获得机器的IP和网卡信息
    Hackerrank
    Android编程之Fragment使用动画造成Unknown animation name: objectAnimator异常
  • 原文地址:https://www.cnblogs.com/do-while-true/p/14145930.html
Copyright © 2011-2022 走看看