您的位置:首页 > 其它

POJ-3537(Crosses and Crosses)——博弈论,SG函数

2015-09-24 19:41 459 查看
题意:两个人玩游戏,规则是在标有1,2,3,4,5...,n的格子上画X,一直画一直画,画到有三个X相邻就获胜。

思路:在试着画了几组之后,明白了要有获胜的情况必须现有类似_XX_和X_X的情况。所以在画X的时候就是要避免这种情况,也就是说在画完一个X之后,这个X的左边两格和右边两格就不可以再画X了(否则对手就赢了)。那么我画完一个X就是将这个游戏分为左半边游戏和右半边游戏,即可以设我画X的位置是第i个格子,那么左半边游戏就是一个新的有i-1-2个格子的游戏(若数字小于等于0,那么这里的SG值就是0),右半边就是一个新的有n-i-2个格子的游戏(如果是负数与前面括号中说得一样),那么就将他们异或起来,即可以算出当前游戏的SG值。然后进行NIM博弈判断,就可以简单的得出赢还是输。(我的i是从1开始取到n,答案和网上从3开始取到n-2的答案一样,其实我是不太懂为什么)

代码:

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <string>
#include <cstdio>
#include <cctype>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define maxn 2000+5
#define PB push_back
#define clr(x,y) memset(x,y,sizeof(x))
int a[maxn];
int SG(int n)
{
if(n<0)return 0;
if(a
>=0)return a
;
bool vis[1000];
clr(vis,0);
for(int i=1;i<=n;i++)
{
int ans=SG(i-1-2)^SG(n-i-2);
vis[ans]=1;
}
int k=-1;
for(int i=0;k==-1;i++)
if(!vis[i])
k=i;
return a
=k;
}
int main()
{
int n;
clr(a,-1);
a[0]=0;
while(~scanf("%d",&n))
{
SG(n);
if(a
!=0)printf("1\n");
else printf("2\n");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: