1. 取走博弈(Take-Away Games)


说好的翻译小能手今天上线啦~ 声明一下,窝是业余滴…练习题是自己做的…不对请留言…

source: comb.pdf


组合博弈是双人游戏,有完善的游戏规则和输赢作为结果。博弈由一系列的状态集(局面)和操作者所决定。每次操作从一个状态转移到另一个状态,直到抵达最后的终态。终态是一个不能再继续操作得到其他状态的局面。那么此时可以宣布其中一人胜出。

对于组合博弈有两种主要的引用,一个是On Numbers and Games by J. H. Conway, Academic Press, 1976。这本书介绍了许多基本的博弈想法,引领了这个领域的快速发展。另一个是更加实用的Winning Ways for your mathematical plays by Berlekamp, Conway and Guy, Academic Press, 1982。在本书中描述了许多有趣的博弈,并且很容易让数学系的学生接受。博弈论被分为两部分,对等博弈(impartial games)是指博弈中的两者可以做一样的操作,有一样的状态集,不对等博弈(partizan games)中两者有不同的状态集。比如下棋时一者下黑棋,另一者下白棋就是不对等的博弈。在第一部分,我们只讨论了对等博弈,一个基本的介绍在Fair Game by Richard K.Guy, published in the COMAP Mathematical Exploration Series, 1989。我们从一个简单的例子开始看。


1.1 一个简单的取走博弈

有一个非常简单的对等组合博弈规则如下:

  1. 有两个游戏者,A和B。
  2. 桌上有21颗石子。
  3. 每次操作可以取走1或2或3颗石子,不可以不取。
  4. 从A开始取,AB轮流操作。
  5. 最后一个可以取石子的人赢。没有石子可取的人输。

怎么分析这个游戏呢?游戏者可以强行赢得游戏吗?你愿意成为其中的A还是B?一个好的策略是什么?

我们从结局开始分析到初始状态,这个方法有时被称为逆向归纳法

如果只剩下1,2或3颗石子,下一个操作的人可以拿走全部石子成为赢家。

假设剩下4颗石子,下一个操作的人必须要拿走1,2或3颗石子,那么他的对手成为赢家。所以面对4颗石子的人会输,前一个留下这4颗石子的人会赢。

如果剩下5,6或7颗石子,那么下一个操作的人可以取到剩下4颗石子,他就赢了。

如果剩下8颗石子,那么下一个操作的人肯定会取到剩下5,6,7颗石子,那么前一个人就赢了。

我们可以看到0,4,8,12,16…是目标局面,我们希望操作之后转移到目标局面。我们现在可以分析这个游戏。因为21不能被4整除,第一个人会赢。唯一的制胜策略是取走1个石子剩下20个石子到达目标局面。


1.2 什么是组合博弈?

我们现在更为准确地定义组合博弈,满足下面几个条件:

  1. 有两个玩家。
  2. 游戏局面是有限集。
  3. 游戏规则针对双方,每个局面的转移都要合法。如果两者的移动规则一样,称为对等博弈(impartial games),否则为不对等博弈(partizan games)
  4. 两者轮流操作。
  5. 当轮到一方已无法继续操作时,游戏结束。在正常的游戏规则下,最后一个操作的人赢。在misere游戏规则下,最后一个操作的人输。
    如果一个游戏没有结局,则称为平局。然而,我们应该加入结束条件(the Ending Condition)来减少平局的可能性。
  6. 游戏在有限步结束。

在定义里省略的一些条件也是重要的。比如不允许随机的操作,如投掷骰子、偷牌,排除了双陆棋、扑克这样的游戏。组合博弈需要完备的信息,同时操作、不操作都是不允许的,排除了石头剪刀布这样的游戏。在有限步数下没有平局,排除了井字棋。除非特别说明,一般都在正常的游戏规则下进行。


1.3 P态,N态

回到1.1中的取石子游戏,我们可以看到0,4,8,12,16…是让前一个操作者赢的状态,1,2,3,5,6,7,9,10,11…是让接下来的操作者赢的状态。前者称为P(Previous)态,后者称为N(Next)态。P态是石子数被4整除的状态,在1.1节中被称为目标状态。

在对等博弈中,可以根据下面的原则来找到P态和N态。我们定义博弈中的终态(Terminal Position)是指没有下一步操作可执行的状态。这个算法就是我们在1.1中用过的方法:

  1. 标记每一个终态为P态。
  2. 标记每一个能到达P态的状态为N态。
  3. 找到通往状态全为N态的状态为P态。
  4. 如果没有新的P态被加入,则停止;否则返回第2步。

很容易看出移到P态的策略会赢。从P态开始,你的对手只能移动到N态,那你又可以移动到P态。最后游戏在终态结束,因为这是个P态,那你就赢了。

对于满足结束条件、在正常规则下的对等组合博弈,关于P态和N态的描述有效,有以下几个特征:

  1. 所有的终态都是P态。
  2. 从每个N态开始,至少可以到达一个P态。
  3. 从每个P态开始,到达的都是N态。

对于misere游戏规则而言,只需把上面的第一条改为终态是N态即可。


1.4 减法博弈(Subtraction Games)

让我们来了解一类组合博弈,1.1中的取石子作为一个特例。令 S 作为一个正整数的集合。两个玩家从n颗石子中轮流取,每次取的数目是S中的一个元素。最后操作的人赢。

在1.1中的取石子博弈是一种减法博弈,其中的 S={1,2,3} 。在练习1.2中,你将会分析 S={1,2,3,4,5,6} 的情况。

让我们分析 S={1,3,4} 的减法博弈并找到P态。这里只有一个终态0。那么1,3,4都是N态,因为它们可以操作到达0。但2是个P态,因为2只能到达1(N态)。然后5,6一定是N态,因为它们可以到达2(P态)。现在我们可以发现7是个P态,因为7只能到达6,4,3,它们均为N态。

现在我们可以继续找到8,10,11是N态,9是P态,12,13是N态,14是P态。这都是通过归纳法扩展得到的。我们可以发现P态集合为 P={0,2,7,9,14,16,...} ,恰好是模7余0或2的非负整数集。N态的集合为 N={1,3,4,5,6,8,10,11,12,13,15,...}

x01234567891011121314
positionPNPNNNNPNPNNNNP

特征串PNPNNNN会循环下去。

如果有100颗石子,谁会赢呢?因为P态满足模7余0或2,而100模7余2,所以100是个P态。第二个玩家会赢。

1.5 练习

1. misere版本

考虑1.1取石子游戏的misere版本,即最后一个拿走石子的人输。那么最好是要迫使你的对手拿走最后的石子。分析此时的P态。

x0123456789
positionNPNNNPNNNP

P态为模4余1的状态。

2. 简单的31取走博弈

正常游戏规则的取走博弈中:a) 假设游戏开始的石子数非常多,每次可以取1到6颗石子,必胜策略如何?P态是什么?b) 如果初始为31颗石子,必胜策略是什么?

x0123456789101112131415
positionPNNNNNNPNNNNNNPN…

P态为7的倍数。每次都让对方面临P态则胜出。
初始为31时,取走3剩下28让对方取。每次都剩下7的倍数让对方取。

3. 31博弈(Geoffrey Mott-Smith (1954))

从一副纸牌中取出每种花色的A,2,3,4,5,6,共24张牌,面朝上放在桌上。玩家轮流翻转纸牌,并把牌上大小累加起来。A记为1。第一个让和超过31的玩家输。这和前面取31颗石子的问题等价。但是注意,每个整数使用不能超过4次。
a) 如果你先翻牌,并且使用了前面练习中的策略,对手一直翻4会怎么样?
b) 尽管如此,你还是可以怎样赢得游戏?

按照之前的策略,P态是和为31,24,17,10,3处,先手会先翻3。由于对方一直翻4,先手一直翻3。当对方翻4后到28,发现4个3都已经用完,无法到达31,这个策略会导致失败。

因为已知对方的策略,赢得游戏的方式可以是选择5个不为4的数,和为15,如1,2,3,3,6.

如果不知道对方的策略,是找不到稳定的N态和P态的。

4. 找到下列减法博弈的P态

a) S={1,3,5,7} .
b) S={1,3,6} .
c) S={1,2,4,8,16,...}= all powers of 2.
d) 石子数从100开始,谁会赢?

写累了,让程序来吧。输入一个S的大小为n,再输入n个元素,打表出30以内的N态和P态。

int a[101], s[10];
int main()
{
    int n;
    while(~scanf("%d", &n)){
        for(int i = 0;i < n;i++)
            scanf("%d", &s[i]);
        memset(a, 0, sizeof(a));
        a[0] = 0;
        for(int i = 1;i < 100;i++) {
            int flag = 1;
            for(int j = 0;j < n;j++) {
                if(i - s[j] >= 0)
                    flag &= a[i - s[j]];
                if(flag == 0) break;
            }
            a[i] = 1-flag;
        }
        for(int i = 0;i < 30;i++)
            printf("%2d%c", i, " \n"[i==30-1]);
        for(int i = 0;i < 30;i++)
            printf(" %c%c", a[i] ? 'N' : 'P', " \n"[i==30-1]);
        printf("100 : %c\n",  a[100] ? 'N' : 'P');
    }
    return 0;
}

5. Empty and Divide(Ferguson (1998))

有两个盒子,初始时分别装m,n个石子。这样的状态被表示为(m,n),其中m>0, n>0. 两个玩家轮流操作。每次操作先选一个盒子倒出所有石子,然后将另一个盒子中的石子取出一些放到空盒子中,要求操作后满足两个盒子非空。唯一的终态为(1,1)。最后操作的玩家胜出。请找到所有的P态。

一言不发就开始打表。

int a[n][n], b[2*n];
int main()
{
    memset(a, 0, sizeof(a));
    memset(b, 0, sizeof(b));
    a[1][1] = b[2] = 0;
    b[1] = 1;
    for(int s = 3;s < n*2-1;s++){
        b[s] = 1;
        for(int i = 1;i < n && i < s;i++) {
            int j = s - i;
            if(j >= n) continue;
            int flag = 1;
            flag = b[i] & b[j];
            a[i][j] = 1 - flag;
            b[s] &= a[i][j];
        }
    }
    for(int i = 1;i < n;i++)
        for(int j = 1;j < n;j++)
            printf("%c%c", a[i][j]?'N':'P', " \n"[j==n-1]);
    return 0;
}

可以发现,当n和m均为奇数时,(n,m)为P态,其余为N态。

6. Chomp!

Fred. Schuh (1952)创造的代数形式的博弈被David Gale (1974)独立地以一种完全不同的形式发现。Gale版本的博弈是从一个m*n的矩形棋盘中移除方格。一次操作是指选定一个方格,移除它在内的右上角中的所有方格。玩家轮流移除方格,移除方格(1,1)的玩家失败。取名为Chomp是因为棋盘被假设为一块巧克力,每次从一些角落开始吃。在(1,1)这格的巧克力是有毒的,吃了它就输了。你可以在这里玩一玩游戏

比如说,巧克力为3行8列,假设第一个人选择(6,2),则吃了右上角的6块。第二个人选择(2,3),吃了右上角的4块。剩下的巧克力如图,打x的是有毒的块。

y\x12345678
3o
2ooooo
1xooooooo

a) 证明现在到了N态并给出制胜策略(唯一)。
b) 已经有人证明了对于所有的矩形先手必胜。证明虽然很精妙但不是很难。然而,这是一个存在性证明。它只证明了先手必胜,但没有给出必胜策略。看看你是否能找到。提示:一直选择右上角是否构成必胜策略?

逆向归纳得到L字形的两臂等长时为P态。那么正方形就是个妥妥的N态了。一般的矩形不知道怎么搞…可以同时开两个游戏页面让计算机对打,观察一下策略…

7. 多样化的减法博弈

可以让减法集依赖于对手最后一次的操作来增加减法博弈的种类。许多早期的例子出现在Schuh (1968)的第12章中。这里有其他两个例子。(可以在Schwenk (1970)中看到概括)

a) 有一堆石子为n。第一个玩家移除大于0小于n的任意多的石子,然后玩家轮流取石子。每个玩家取的石子不能超过对手上次取的石子数。如果n=44,第一个玩家的制胜策略是什么?n为多少时,第二个玩家会赢?
b) Fibonacci Nim (Whinihan (1963)) 每个玩家取得石子不能超过对手上次取的石子的两倍,其余的规则和a中一样。这个游戏的分析比之前a中的更难,它依赖于Fibonacci数列。Zeckendorf’s Theorem有助于形成这个数列。它是说每个正整数可以惟一地写成不相邻的Fibonacci数列里的数之和。

把一个数写成Fibonacci数列里的数字之和有很多写法,但要求不相邻项就只有一种写法。因此,43=34+8+1是43唯一的拆法,因为43=34+5+3+1里,5和3是相邻的。如果n=43,第一个玩家的制胜策略是什么?n为多少时,第二个玩家会赢?你可以去玩一玩

a) 列表n表示石头数目,m表示第一次取得数目小于等于m.带括号的N表示途径该状态时为N态,但不能为初始状态。

m\n12345678910
1(N)PNPNPNPNP
2(N)NPNNNPNN
3(N)PNNNPNN
4(N)NNNPNN

归纳可以得到,n为2的幂次时为P态,其余为N态。这里的N态和P态不像之前那么清真,要看对手的走法,避免把自己搞到P态上去。
n=44时为N态,第一次取12为制胜策略。

b) 和a类似打表如下。

m\n12345678910
1(N)PPNPNNPNN
2(N)(N)PNPNNPNN
3(N)(N)(N)NPNNPNN
4(N)(N)(N)(N)PNNPNN

其实规则改为“每个玩家取得石子不能超过对手上次取的石子的k倍”,可以打表得到。这个表里n下面有n-1个P的即说明是P态。

#define N 40
int a[N+10][N*N];
int main(){
    int k;
    while(~scanf("%d", &k)) {
        memset(a, -1, sizeof(a));
        for(int n = 2;n < N;n++)
            for(int m = 1;m < n;m++) {
                if(a[n-m][m*k] == 0) {
                    a[n][m] = -1;
                    break;
                }
                a[n][m] = 0;
            }
        for(int i = 1;i < 40;i++)
            printf("%2d%c", i, " \n"[i==39]);
        for(int i = 1;i < 40;i++)
            for(int j = 1;j < 40;j++)
                printf(" %c%c", a[j][i] ? ' ' : 'P', " \n"[j==39]);
    }
}

8. SOS博弈 (From the 28th Annual USA Mathematical Olympiad, 1999)

一个棋盘有一行n格,初始为空。玩家轮流挑选空白的格子填字母S或O。第一个完成连续的SOS的人胜出。如果没有SOS出现,则平局。

a) 假设n=4,第一个人在第一格填S,证明第二个人会赢。
b) 证明n=7时,第一个人会赢。
c) 证明n=2000时,第二个人会赢。
d) n=14时,是否有谁会赢呢?

a) 填法

SS

这样先手就很尴尬了。后手必胜。


  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值