NimGame 尼姆博弈

问题

AABB两人轮流从nn堆物品中取出一些物品,nn堆物品的数量分别为[s1,s2,s3sn][ s_{1}, s_{2}, s_{3} \dots s_{n} ](所有物品数量都是正整数)。

每人每次从一堆物品中至少取11个,多则不限,最后取光所有物品的人获胜。

给定nn[s1,s2,s3sn][ s_{1}, s_{2}, s_{3} \dots s_{n} ],当我方先手,我方和对方都是高手(在能赢的情况下一定能赢),求我方是否能赢。

解法

(1)(1) 当我方面临[0,7,0][0, 7, 0]局势(有11堆物品)时,我方必赢,因为我方可以一次把剩下一组的物品取光;

(2)(2) 当我方面临[0,1,1,0,0][0, 1, 1, 0, 0]局势(有22堆物品且均剩11个)时,我方必输,因为我方必然留给对方只剩11堆物品的局势;

(3)(3) 当我方面临[0,1,1,1,0][0, 1, 1, 1, 0]局势(有33堆物品且均剩11个)时,我方必赢,因为我方必然留给对方只剩22堆物品且均剩11个的局势;

(4)(4) 当我方面临[3,4,5][3, 4, 5]局势时,暂时无法看出我方是否必赢;

\cdots

本问题背后的数学模型叫NimSumNim Sum,堆数组大小的二进制和,上面55个局势可以转化为:

s1=010=0002s2=710=1112s3=010=0002nim1=070=1\begin{matrix} s_{1} = 0_{10} = 000_{2} \\ s_{2} = 7_{10} = 111_{2} \\ s_{3} = 0_{10} = 000_{2} \\ nim_{1} = 0 \oplus 7 \oplus 0 = 1 \end{matrix}
s1=010=0002s2=110=0012s3=110=0012s4=010=0002s5=010=0002nim2=01100=0\begin{matrix} s_{1} = 0_{10} = 000_{2} \\ s_{2} = 1_{10} = 001_{2} \\ s_{3} = 1_{10} = 001_{2} \\ s_{4} = 0_{10} = 000_{2} \\ s_{5} = 0_{10} = 000_{2} \\ nim_{2} = 0 \oplus 1 \oplus 1 \oplus 0 \oplus 0 = 0 \end{matrix}
s1=010=0002s2=110=0012s3=110=0012s4=110=0012s5=010=0002nim3=01110=1\begin{matrix} s_{1} = 0_{10} = 000_{2} \\ s_{2} = 1_{10} = 001_{2} \\ s_{3} = 1_{10} = 001_{2} \\ s_{4} = 1_{10} = 001_{2} \\ s_{5} = 0_{10} = 000_{2} \\ nim_{3} = 0 \oplus 1 \oplus 1 \oplus 1 \oplus 0 = 1 \end{matrix}
s1=310=0112s2=410=1002s3=510=1012nim4=345=2\begin{matrix} s_{1} = 3_{10} = 011_{2} \\ s_{2} = 4_{10} = 100_{2} \\ s_{3} = 5_{10} = 101_{2} \\ nim_{4} = 3 \oplus 4 \oplus 5 = 2 \end{matrix}

可以看出,当我方面临i=1nsi=s1s2sn0\oplus_{i=1}^{n} s_{i} = s_{1} \oplus s_{2} \oplus \cdots \oplus s_{n} \ne 0局势时必赢,否则必输。

该算法时间复杂度为O(n)O(n)

Nim Sum

源码

NimGame.h

NimGame.cpp

测试

NimGameTest.cpp

Last updated