其他
两人取石子游戏:组合数学-博弈问题
(给算法爱好者加星标,修炼编程内功)
作者:obshilu
https://blog.csdn.net/ojshilu/article/details/16812173
取石子游戏是一个古老的博弈游戏,据说是发源于中国,它是组合数学领域的一个经典问题。
它有许多不同的玩法,基本上是两个玩家,玩的形式是轮流抓石子,胜利的标准是抓走了最后的石子。
玩家设定: 先取石子的是玩家A,后取石子的是玩家B。
经典的三种玩法:
一、Bash Game,有1堆含n个石子,两个人轮流从这堆物品中取物,规定每次至少取1个,最多取m个。取走最后石子的人获胜。
二、Nimm Game,有k堆各n个石子,两个人轮流从某一堆取任意多的物品,规定每次至少取一个,多者不限。取走最后石子的人获胜。
三、Wythoff Game,有2堆各n个石子,两个人轮流从某一堆或同时从两堆中取同样多的物品,规定每次至少取1个,多者不限。取走最后石子的人获胜。
平衡状态的概念:
引入一个概念,平衡状态,又称作奇异局势。当面对这个局势时则会失败。任意非平衡态经过一次操作可以变为平衡态。
每个玩家都会努力使自己抓完石子之后的局势为平衡,将这个平衡局势留给对方。
因此,玩家A能够在初始为非平衡的游戏中取胜,玩家B能够在初始为平衡的游戏中取胜。
玩法二(k堆石子每次只从1堆取):
玩法三(2堆石子每次从一或两堆取一样数目的石子):
Ak = [k*(1+sqrt(5.0)/2]
Bk = Ak + k
其中k=0,1,2,...,n ,方括号表示int取整函数。
#include<cmath>
#include<iostream>
using namespace std;
const double m = (1+sqrt(5.0))/2;
void display()
{
int i;
int out;
for(i=0;i<30;i++)
{
out = int(m*i);
cout << "(" << out << ", " << out+i << ")" << endl;
}
}
bool judge(int a, int b)
{
int k = a/m;
if ( a == int(k*m) )
{
if( b == a + k )
return true;
}
else if( a == int((k+1)*m) )
{
if(b == a + k + 1 )
return true;
}
return false;
}
void main()
{
int a, b;
cin >> a >> b;
cout << judge(a,b) << endl;
}
- EOF -
觉得本文有帮助?请分享给更多人
推荐关注「算法爱好者」,修炼编程内功
点赞和在看就是最大的支持❤️