NOJ 1177 跳马 SG函数,博弈

NOJ 1177 跳马 SG函数,博弈

先贴个代码,博弈问题还要继续深究,special thanks to thinkking!
原题:

相信大家都玩过象棋,象棋中马跳日。Alice Bob现在想玩一个游戏,在一个n * n的棋盘,棋盘中放了m个马。游戏规则如下:

1)  Alice先手

2)  玩家轮流操作,每次合法操作是将其中一个马按照日移到其左上方一点,注意只能往左上方移动。最左上方的位置是( 1  1 ),同一位置可以有多个马,但是每次移动只能移动一个马。

玩家都很有谋略,他们都以最优策略来下每一步。问最后谁能取胜



Input

第一行输入整数t ( t < = 100 ), 则有t 个case。每个case 先输入 棋盘的大小 n ( n < = 500 ) ,马的个数 m( m < = 20000 )下面m行输入马的坐标位置 x ,y ( 1 = < x < = 500 1 = < y < = 500 )

Output

对于每个case 输出谁会获得最终胜利。注意:马只要是日就可以跳,而不需要满足象棋中的一些其他规矩

SampleInput

2
5 2
2 2
2 3
5 2
3 3
2 3

SampleOutput

Case 1: Alice
Case 2: Bob

#include < iostream >
#include
< cmath >
using   namespace  std;

int  n,m;
int  dir[ 2 ][ 2 ] = {{-1,-2},{-2,-1}} ;

bool  god( int  x, int  y)
{
    
if(x<1||x>500||y<1||y>500)
        
return false;
    
return true;
}

int   const  maxn = 510 ;
int  SG[maxn][maxn];

struct  node
{
    
int x,y;
}
q[ 20020 ];

int  v[ 3 ];
int  main()
{

    
int ca;
    scanf(
"%d",&ca);
    
int cn=0;
    
for(int i=1;i<=500;i++)
    
{
        
for(int j=1;j<=500;j++)
        
{
            memset(v,
0,sizeof(v));
            
for(int k=0;k<2;k++)
            
{

                
int nx=i+dir[k][0];
                
int ny=j+dir[k][1];
                
if(god(nx,ny))
                
{
                    v[SG[nx][ny]]
=1;
                }

            }

            
for(int k=0;k<=2;k++)
            
{
                
if(v[k]==0)
                
{
                    SG[i][j]
=k;
                    
break;
                }

            }


        }

    }

    
while(ca--)
    
{
        cn
++;
        scanf(
"%d%d",&n,&m);
        
for(int i=1;i<=m;i++)
            scanf(
"%d%d",&q[i].x,&q[i].y);
        
        
int ans=0;
        
for(int i=1;i<=m;i++)
        
{
            ans
^=SG[q[i].x][q[i].y];
        }

        
if(ans)
            printf(
"Case %d: Alice\n",cn);
        
else
            printf(
"Case %d: Bob\n",cn);
    }

    
return 0;
}

你可能感兴趣的:(NOJ 1177 跳马 SG函数,博弈)