zoukankan      html  css  js  c++  java
  • 纪中集训-游戏

    题目链接

    (是纪中的题,不过我已经没有纪中的号了,于是翻出了我的古早博客

    题目解析

    复习的时候又做了一遍,还是想了一会儿的,并且由衷地觉得这真是一道好题。

    考虑(SG)函数递推。

    由于每次操作只能动最后一行和最后一列,那么设(sg(i,j))表示以((i,j))结尾的矩阵的(SG)函数值。

    转移有:(sg(i,j)=mex{sg(i-1,j),sg(i,j-1) }),不过转移的时候需要满足对应的这一行/列的和为偶数才能转移(和为偶数才能操作,也就是说这一列的和为偶数,((i,j-1))才是后继状态,同理行也是这样)

    初始的(sg(0,0)=0)(什么都没有了,不能操作了,对于先手来说是必败态


    然后我们发现其实定义(mex)这个东西有点鸡肋,我们可以考虑改变(sg)的定义,设(sg(i,j))表示以((i,j))结尾的矩阵是对于当前操作者是必败态(为(0)),还是必胜态(为(1))。

    转移的话,可转移的后继状态中,只要有一个必败态((sg=0)),那么它就可以是必胜态((sg=1)

    边界情况:

    (sg(1,1)=a[1][1]\%2)

    然后是单独剩下的第一行和第一列,拿第一行举例子吧,第一列同理。对于只剩下第一行的情况,可以一次删掉右边最后一列,也可以删掉这一整行。如果删列的话,那么(sg)是从左边转移过来的,没有影响。如果是删掉一整行的话,只需要判断到当前这个位置的和是不是偶数,是偶数就是必胜态,但如果我们把(sg[i-1][j])设为(0)的话,就不需要特判,可以自动转移。


    ►Code View

    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    using namespace std;
    #define N 1005
    #define LL long long
    int rd()
    {
    	int x=0,f=1;char c=getchar();
    	while(c<'0'||c>'9'){if(c=='-') f=-1; c=getchar();}
    	while(c>='0'&&c<='9'){x=(x<<1)+(x<<3)+(c^48); c=getchar();}
    	return f*x;
    }
    int s1[N][N]/*行的前缀和*/,s2[N][N]/*列的前缀和*/,sg[N][N];
    int main()
    {
    	int T=rd();
    	while(T--)
    	{
    		int n=rd();
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    			{
    				int a=rd()%2;
    				s1[i][j]=(s1[i-1][j]+a)%2;
    				s2[i][j]=(s2[i][j-1]+a)%2;
    				sg[i][j]=0;
    				if(!s1[i][j])//这一列可以删掉
    					if(!sg[i][j-1]) 
    						sg[i][j]=1;
    				if(!s2[i][j])//这一行可以删掉
    					if(!sg[i-1][j]) 
    						sg[i][j]=1; 
    			}
    		if(sg[n][n]) puts("W");
    		else puts("L");
    	}
    	return 0;
    }
    /*
    2
    2
    2 4 
    6 8
    3
    5 4 2
    1 5 9
    7 3 8
    */
    
  • 相关阅读:
    centos 给终端设快捷键
    centos 给鼠标右击添加 “打开终端” 菜单项
    centos 6.X 安装输入法
    centos U盘安装
    js的构造函数
    onresize的定义方式
    两个时间对比
    AMD和CMD的区别
    spring加载配置文件
    cglib代理
  • 原文地址:https://www.cnblogs.com/lyttt/p/14086913.html
Copyright © 2011-2022 走看看