• bzoj1457 棋盘游戏


    题目描述:

    $100*100$的棋盘上有$n$个$Queen$,每个$Queen$可以向左,向下,向左下移动。

    两人轮流操作,将任何一个$Queen$移动到$(0,0)$的人获胜。

    一个位置上可以有很多$Queen$,$Queen$移动时不需要考虑经过路径上是否有$Queen$。

    题解:

    这个很像$Nim$游戏,不过这个游戏是移动一个到$(0,0)$即可。

    两个人都不是傻子,所以有其他选择之前都不会给对方送棋。

    所以我们可以猜到起手不能到$(0,0)$的情况下,一定会有所有$Queen$聚集在$(1,2)$和$(2,1)$的壮观场面。

    两步之后,游戏结束。

    所以有棋子可以直接到$(0,0)$时,先手获胜;

    其他情况下,将最后一个$Queen$移动到$(1,2)$或$(2,1)$的人获胜。

    这两个点相当于终止节点。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 105;
    int T,n,sg[N][N];
    int dfs(int x,int y)
    {
        if(~sg[x][y])return sg[x][y];
        if((x==1&&y==2)||(x==2&&y==1))return sg[x][y]=0;
        bool tmp[10*N]={0};
        for(int i=1;i<x;i++)if(x-i!=y)tmp[dfs(x-i,y)]=1;
        for(int i=1;i<y;i++)if(y-i!=x)tmp[dfs(x,y-i)]=1;
        for(int i=1;i<x&&i<y;i++)tmp[dfs(x-i,y-i)]=1;
        for(int i=0;;i++)if(!tmp[i])return sg[x][y]=i;
    }
    int main()
    {
        scanf("%d",&T);
        memset(sg,-1,sizeof(sg));
        while(T--)
        {
            scanf("%d",&n);
            int ans = 0;
            bool ot = 0;
            for(int x,y,i=1;i<=n;i++)
            {
                scanf("%d%d",&x,&y);
                if(x&&y&&x!=y)ans^=dfs(x,y);
                else ot=1;
            }
            if(ot)puts("^o^");
            else puts(ans?"^o^":"T_T");
        }
        return 0;
    }
  • 相关阅读:
    yield return 和 Func
    匿名类型与扩展方法
    对象初始化器和集合初始化器
    VSCode编辑器使用技巧:快捷输入HTML代码
    CSS清除浮动
    置换元素与非置换元素
    浏览器五大内核及代表
    IE过滤器
    写个 Hello world 前端从入坑到弃坑系列教程(1)
    测试一下
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/10306659.html
Copyright © 2020-2023  润新知