博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

bzoj:1457: 棋盘游戏

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1457

看了网上dalao的题解,好像解释得并不是很清楚,就按照那种思路,自己YY了一个想法,写出来居然跟std是一样的。

首先如果刚开始棋盘上有X=0或Y=0或X==Y先特判掉。

如果我们把走到(0,0)对应于将一堆石子取空,那么剩下的难点在于一般的Nim游戏是所有石子堆均被取空则游戏结束,而这里只要一堆空就结束了,这很气……

那么我们需要考虑转换一下一堆石子被取空时对应的情景。

如果有人走到X=0或Y=0或X==Y,对手即刻就胜利了,最优策略里谁都不会这么走,也就是说,走到X=0或Y=0或X==Y这种情况是不被允许的。要是有人实在没办法走别的地方,必须走这里,他就输了。这里就转化为不允许走到X=0或Y=0或X==Y,谁无法在这一限制内继续行动,就是失败者。

这样一来就是正常的Nim题了。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 1000
using namespace std;

int read_p,read_ca;
inline int read(){
    read_p=0;read_ca=getchar();
    while(read_ca<'0'||read_ca>'9') read_ca=getchar();
    while(read_ca>='0'&&read_ca<='9') read_p=read_p*10+read_ca-48,read_ca=getchar();
    return read_p;
}
int T,n,m,a,b,mmh,MMH,sg[100][100];
bool bo[1001];
int main(){
    register int i,j;
    for (i=1;i<100;i++)
    for (j=1;j<100;j++)
    if (i!=j){
        memset(bo,0,sizeof(bo));
        for (int k=1;k<i&&k<j;k++) bo[sg[i-k][j-k]]=1;
        for (int k=1;k<i;k++) if (i-k!=j) bo[sg[i-k][j]]=1;
        for (int k=1;k<j;k++) if (i!=j-k) bo[sg[i][j-k]]=1;
        for (int k=0;;k++) if (!bo[k]){sg[i][j]=k;break;}
    }
    T=read();
    while (T--){
        n=read();mmh=MMH=0;
        while (n--){
            a=read();b=read();
            if (a==0&&b==0) MMH|=2;
            if (a==0||b==0||a==b) MMH|=1;else mmh^=sg[a][b];
        }
        if (MMH) puts(MMH==1?"^o^":"T_T");else puts(mmh?"^o^":"T_T");
    }
}
View Code

YY成功真开心。

posted @ 2017-04-05 21:04  swm_sxt  阅读(398)  评论(0编辑  收藏  举报