博弈小结(备忘录)

来源:互联网 发布:淘宝广州模特招聘骗局 编辑:程序博客网 时间:2024/05/22 14:58

巴什博奕(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
原创粉丝点击