Bootstrap

博弈论三种基础模型(Bashgame,Wythoffgame,Nimmgame)

Bashgame

问题模型:只有一堆n个物品,两个人轮流从这堆物品中取物品,规定每次至少取一个,最多取m个,最后取光者得胜

结论: 若 n % (m+1) == 0,则先手必败; 否则,先手必胜。 

先手代码

int x,y;
cin >> x >> y;
if(x % (y + 1) == 0) cout << "lose";
else cout << "win";

Wythoffgame

问题模型:有两堆各若干个物品,两个人轮流从任意一堆中取出至少一个或者同时从两堆中取出同样多的物品,规定每次至少取一个,多者不限,最后取光者得胜

结论:设两堆物品数分别为a和b(a < b),计算 k = b - a,然后 s = (double)(k * (sqrt(5.0) + 1) / 2)。若 s == a,则先手必败;否则,先手必胜。

先手代码:

int x,y;
cin >> x >> y;
if(x > y) swap(x,y);//保证x<y
double a,b;
a = (sqrt(5.0) + 1)/2;
b = (double)(y-x);
int s = a*b;
if(s == x) cout << "lose";
else cout << "win";

Nim1game

问题:N堆各若干个物品(数目为x,y,z),两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限,最后取光者得胜

结论:对每堆的数目进行亦或(XOR)操作后,若结果为0,则当前局面为必败态;否则,为必胜态。这一结论可以推广到n堆物品的情况。

先手代码

int x,y,z;
cin >> x >> y >> z;
cout << (x^y^z == 0);//必输
cout << (x^y^z != 0);//必赢

Nimkgame(较为少见)

Nim1是Nimk的特殊形式

Nim1是每次只能取一个堆,而 Nimk是指每次可以取K个堆(每个堆数量任意)

实际上Nimmgame的结论为:将N堆数字转换为二进制后,用(每一位1的个数)%(k+1) == 0就是必败态,而当Nim1时,就时%2,也就是等于异或的结果。

注意:四个模型都是先取完获胜

;