zoukankan      html  css  js  c++  java
  • SCU 3132(博弈)

    传送门:windy和水星 -- 水星游戏 1 

    题意:在一张由 n*m 的格子组成的棋盘上放着 k 个骑士每个骑士的位置为(xi,yi),表示第xi行,第yi列骑士如果当前位置为(x,y),一步可以走的位置为

    (x-2,y-1)

    (x-2,y+1)

    (x-1,y-2)

    (x+1,y-2)

    两人对弈,每次移动一个骑士,在同一时间可有多个骑士在同一格子,谁不能移动谁输现在给定初始棋面,问先手是否有必胜的策略?

    分析:将k个骑士当成k个子游戏,然后求出k个子游戏的sg值,然后问题转换成有k堆石子,每堆有sg[i]个石子,先手可以选择一堆取1~sg[i]个石子,取完最后的石子的人赢,这就变成裸Nim游戏,将所有sg值异或判断是否为0即可。

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define N 110
    using namespace std;
    int n,m,k;
    int sg[N][N];
    int dx[]={-2,-2,-1,1};
    int dy[]={-1,1,-2,-2};
    bool judge(int a,int b)
    {
        return a>=0&&a<n&&b>=0&&b<m;
    }
    int dfs(int x,int y)
    {
        if(~sg[x][y])return sg[x][y];
        int vis[5],temp;
        memset(vis,false,sizeof(vis));
        for(int i=0;i<4;i++)
        {
            int a=x+dx[i],b=y+dy[i];
            if(!judge(a,b))continue;
            if((temp=sg[x][y])==-1)temp=dfs(a,b);
            vis[temp]=1;
        }
        for(int i=0;i<5;i++)
        {
            if(vis[i])continue;
            return sg[x][y]=i;
        }
    }
    int main()
    {
        while(scanf("%d%d%d",&n,&m,&k)>0)
        {
            memset(sg,-1,sizeof(sg));
            sg[0][0]=sg[0][1]=sg[1][0]=sg[1][1]=0;
            for(int i=0;i<n;i++)
                for(int j=0;j<m;j++)
                if(sg[i][j]==-1)dfs(i,j);
            int x,y,flag=0;
            while(k--)
            {
                scanf("%d%d",&x,&y);
                flag^=sg[x][y];
            }
            if(flag)puts("yes");
            else puts("no");
        }
    }
    View Code
  • 相关阅读:
    Git 数据是怎么存储的
    技术管理规划-路径跟资源
    技术管理规划-如何规划团队的架构
    技术管理规划-如何设定团队的目标
    技术管理规划-设定团队的职能
    springboot实践1
    spring的事件机制实战
    Apollo的基本概念和集成实战
    spring的事件
    ELK的简单安装使用
  • 原文地址:https://www.cnblogs.com/lienus/p/4326357.html
Copyright © 2011-2022 走看看