I - Game of Hyper Knights
A Hyper Knight is like a chess knight except it has some special moves that a regular knight cannot do. Alice and Bob are playing this game (you may wonder why they always play these games!). As always, they both alternate turns, play optimally and Alice starts first. For this game, there are 6 valid moves for a hyper knight, and they are shown in the following figure (circle shows the knight).
They are playing the game in an infinite chessboard where the upper left cell is (0, 0), the cell right to (0, 0) is (0, 1). There are some hyper knights in the board initially and in each turn a player selects a knight and gives a valid knight move as given. And the player who cannot make a valid move loses. Multiple knights can go to the same cell, but exactly one knight should be moved in each turn.
Now you are given the initial knight positions in the board, you have to find the winner of the game.
Input
Input starts with an integer T (≤ 200), denoting the number of test cases.
Each case starts with a line containing an integer n (1 ≤ n ≤ 1000) where n denotes the number of hyper knights. Each of the next n lines contains two integers x y (0 ≤ x, y < 500) denoting the position of a knight.
Output
For each case, print the case number and the name of the winning player.
Sample Input
2
1
1 0
2
2 5
3 5
Sample Output
Case 1: Bob
Case 2: Alice
刚开始看到棋盘问题的时候感觉从某一个点开始的话就是可以进行的操作能够到达的点就是他的后继状态,打表预处理枚举就可以了,但是一直wa去搜了一下题解才知道,二维棋盘博弈问题,并不是递推出现的,换句话说就是当你看x,y点的时候,比他小的所有点的sg函数值你都已经求出来,因为比 x, y小的点你可以由比x,y都打的点走到,但是这个时候你如果是用递推来做的话就是默认这个状态的sg值是零这样是不对的。
例如:
这道题目中如果是我们要求的是row=3,clown=3 这个位置的sg值我们会用row=4,clouwn=1这个位置作为他的后继状态,
但是如果是我们在用暴力跑的时候会发现,在求(3,3)这个店的sg值的时候,(4,1)这个点sg值我们还没有算,如果只是仅仅是简单的暴力的话我们就默认了这个位置的sg=0这个样子显然是不合法的,所以我们这里要把问题分解成功能类似,但是规模不断变小的问题递归;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define rep(i,s,n) for(ll i=s;i<=n;i++)
#define per(i,n,s) for(ll i=n;i>=s;i--)
const int Max = 1e3+10;
int sg[Max][Max];
int dx[10]={-2, -3, -2, -1, -1, 1};
int dy[10]={1 , -1, -1, -2, -3, -2};
int DFS(int x, int y){
if(sg[x][y]!=0) return sg[x][y];
bool visited[Max];
rep(i,0,600) visited[i]=false;
rep(i,0,5){
int nowx=x+dx[i];
int nowy=y+dy[i];
if(nowx>=0&&nowy>=0) visited[DFS(nowx,nowy)]=1;
}
rep(i,0,600)
if(!visited[i]){
sg[x][y]=i;
break;
}
return sg[x][y];
}
int main(){
int t,ca=1;
sg[0][0]=0;
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
int key=0;
rep(i,1,n){
int x,y;
scanf("%d %d",&x,&y);
key^=DFS(x,y);
}
printf("Case %d: ",ca++);
if(key) printf("Alice\n");
else printf("Bob\n");
}
return 0;
}