博弈小结(备忘录)


巴什博奕(Bash Game):
    描述:一堆石子,共n个。两人轮流取1~m
个石子走,到最后谁能把剩下的一次性去光谁就赢了。
    解析:将全部n个石头分解为n = (m+1)*k + t个。先手先取t个,假设后手取x个(1 <= x <= m),那么先手再取m+1-x个,局面就变为n = (m+1)*(k-1)个;以后只要一直按照x、m+1-x这样取下去,先手必胜。例如:两人数30,每次1~4个数,假设先手数x,那么后手只要数4+1-x个数,这样下去每次都是少5个数,最后当然后手胜。所以谁面对了n = (m+1)*k + t,t这个"零头",即能拿走这个零头,剩余m+1的倍数,谁就胜利。

    总结: if(n % (m+1)  != 0)先手胜

#include<iostream>
using namespace std;
int main()
{
int n, m;
while(~scanf("%d%d", &n, &m))
{
if(n % (m+1) == 0)
printf("first lose\n");
else
printf("first win\n");
}
return 0;
}

威佐夫博奕(Wythoff Game):
    描述: 有两堆石子,分别有n和m个石子。取石头的规则是:从一堆中至少取一个,至多全取走,或者从两堆中取走相同数目的石子。 谁将最后的取光谁就赢。
    解析: 解析和证明 较复杂,另参照网上的解析。
    总结: if(floor((num2 - num1) * (1 + sqrt(5.0)) / 2.0) != num1) 先手败

#include<iostream>
#include<cmath>
using namespace std;

int main()
{
int num1, num2;
while(~scanf("%d%d", &num1, &num2))
{
if(num1 > num2)
{
num1 ^= num2;
num2 ^= num1;
num1 ^= num2;
}
int x = floor( (num2-num1) * (1+sqrt(5.0)) / 2.0 );
if(x != num1)
printf("first win\n");
else
printf("first lose\n");
}
return 0;
}

尼姆博奕(Nim Game):
    描述:
有n堆石头,每堆石头有num[i]个石子。双方每次从一堆中取走至少一个,至多全部。谁取走最后的石子谁就胜利。
    解析:所有石子的异或值为零的话,当前必败,即先手必败。
    总结: for(1~n){ re ^= num[i] }; if(re == 0)先手败

#include<iostream>
#include<cmath>
using namespace std;

int num[100];

int main()
{
int n;
while(~scanf("%d", &n))
{
int re = 0;
for(int i = 1; i <= n; i++)
{
scanf("%d", &num[i]);
re ^= num[i];
}
if(re)
printf("first win\n");
else
printf("first lose\n");
}
return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值