• [51nod1329]路径游戏


      Snuke与Sothe两个人在玩一个游戏。游戏在一个2*N的网格中进行(2行N列),这个网格中的2N个格子不是黑色就是白色。定义,一条有效路径是指一个完全由白色格子构成的序列,这个序列的第一个网格元素是最左端两个网格之一,最后一个元素是最右端两个网格之一,且在序列中任意两个连续元素在网格中是边相邻的。(任意一个格子与其上下左右四个方向上的网格边相邻,当然在2*N网格中,一个格子只有最多3个相邻的格子。)游戏初始时确保这个网格中存在至少一条有效路径。游戏开始后Snuke与Sothe轮流进行操作,每一次操作需要选择网格中的一个白格并将其涂黑,且操作后的网格中必须依然存在至少一条有效路径。若一个人操作完后网格中不再存在有效路径的话,该操作选手判为输,而另一个选手为赢。假设Snuke与Sothe两人都采用最优策略,且Snuke先手。那么请问对给定的初始网格涂色状态,谁是最终的赢家?

      例如,初始状态如下:('.'表示白色,‘#’表示黑色)
    #..
    ...
      Snuke必须先手把右下角涂黑,
    #..
    ..#
      而此时Sothe将无路可走。
     Input
      多组测试数据。
      第一行一个整数T,表示数据个数,其中1<=T<=5。
      接下来3T行,是T组不同的数据。
      每组数据由3行构成,其第一行是一个整数N,其中1<=N<=1000
      接下来两行每行N个字符,表示网格中每个格子的初始颜色,'.'表示白色,‘#’表示黑色。
     Output
      每组数据一行输出,输出获胜玩家名字。

      直接求SG函数。。sg[i][ztl][ztr]表示中间2*i个全空的格子,再往左右那两列有无障碍格子的状态分别为ztl,ztr 的SG值。

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<cmath>
     7 #include<cstdlib>
     8 #define ll long long
     9 #define ull unsigned long long
    10 #define ui unsigned int
    11 #define d double
    12 #define ld long double
    13 const int maxn=2333,modd=1000000007;
    14 
    15 int sg[1012][4][4];
    16 int u[23333];
    17 char s1[maxn],s2[maxn];
    18 int i,j,k,n,m;
    19 
    20 int ra,fh;char rx;
    21 inline int read(){
    22     rx=getchar(),ra=0,fh=1;
    23     while(rx<'0'&&rx!='-')rx=getchar();
    24     if(rx=='-')fh=-1,rx=getchar();
    25     while(rx>='0')ra=ra*10+rx-48,rx=getchar();return ra*fh;
    26 }
    27 
    28 inline void getsg(){
    29     int i,ztl,ztr,tim=0;register int j;
    30     for(i=0;i<=1000;i++)for(ztl=3;ztl>=0;ztl--)for(ztr=3;ztr>=0;ztr--)
    31         if((i>0&&ztl!=3&&ztr!=3)||(!i&&((ztl|ztr)!=3))){
    32             tim++;
    33             for(j=0;j<i;j++){
    34                 if((j>0&&j<i-1)|| ((j||!(ztl&2))&&(j<i-1||!(ztr&2))) )u[sg[j][ztl][1]^sg[i-j-1][1][ztr]]=tim;
    35                 if((j>0&&j<i-1)|| ((j||!(ztl&1))&&(j<i-1||!(ztr&1))) )u[sg[j][ztl][2]^sg[i-j-1][2][ztr]]=tim;
    36             }//printf("trying:    %d %d %d
    ",i,ztl,ztr);
    37             if(!ztl&&(i>0||!(ztr&2)))u[sg[i][1][ztr]]=tim;
    38             if(!ztl&&(i>0||!(ztr&1)))u[sg[i][2][ztr]]=tim;
    39             if(!ztr&&(i>0||!(ztl&2)))u[sg[i][ztl][1]]=tim;
    40             if(!ztr&&(i>0||!(ztl&1)))u[sg[i][ztl][2]]=tim;
    41             
    42             for(j=0;u[j]==tim;j++);sg[i][ztl][ztr]=j;//if(i<3)printf("    SG:%d  %d %d  %d
    ",i,ztl,ztr,j);
    43         }else sg[i][ztl][ztr]=233333;
    44 }
    45 
    46 int main(){
    47     getsg();
    48     for(int T=read();T;T--){
    49         int len=0,SG=0;
    50         m=read();
    51         scanf("%s%s",s1+1,s2+1);
    52         if(m==1)SG=(s1[1]=='.'&&s2[1]=='.')?1:0;
    53         for(i=2;i<=m;i++)
    54             if(s1[i]=='.'&&s2[i]=='.'&&i<m)len++;
    55             else{
    56                 int ztl=(s1[i-len-1]=='#')<<1|(s2[i-len-1]=='#'),ztr=(s1[i]=='#')<<1|(s2[i]=='#');
    57             //    printf("SG:%d  %d %d   %d
    ",len,ztl,ztr,sg[len][ztl][ztr]);
    58                 SG^=sg[len][ztl][ztr],len=0;
    59             }
    60         puts(SG?"Snuke":"Sothe");
    61     }
    62 }
    View Code
  • 相关阅读:
    最小堆
    HDU1022+栈
    POJ2318+几何+判点在四边形内
    HDU1003+最大连续子序列和+起始终止位置
    HDU1174+三维点到直线距离
    HDU4517
    Two Phase Commit (2PC) [转]
    分布式系统领域经典论文翻译集 [转]银河里的星星
    每个程序员都应该知道的8个LINUX命令 [转]
    Google File System解析 [转]
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5950978.html
Copyright © 2020-2023  润新知