HDU 5754
题意:
一个n*m的棋盘,左上角为(1, 1), 右下角为(n, m),棋子一开始在(1, 1),两人轮流移动棋子,先把棋子移动到(n, m)的获胜,如果无法将棋子移动到(n, m),则记为平局(棋子只能由左到右, 由上到下移动);
有四种棋子:
king:横、直、斜都可以走,但每次限走一步;
rook:横、竖均可以走,步数不受限制,不能斜走;
knight:每步棋先横走或直走一格,然后再往外斜走一格;或者先斜走一格,最后再往外横走或竖走一格(即走"日"字);
queen:横、直、斜都可以走,步数不受限制;
思路:
对每种棋子预处理打表;
#include <bits/stdc++.h>
using namespace std;
int sg_k[1010][1010], sg_r[1010][1010], sg_kn[1010][1010], sg_q[1010][1010];
int judge_k(int x, int y){
if(sg_k[x-1][y]==0 || sg_k[x][y-1]==0 || sg_k[x-1][y-1]==0) return 1;
return 0;
}
void SG_king(){
for(int i=0; i<=1000; i++) sg_k[i][0]=1;
for(int j=0; j<=1000; j++) sg_k[0][j]=1;
for(int i=1; i<=1000; i++){
for(int j=1; j<=1000; j++){
sg_k[i][j]=judge_k(i, j);
}
}
}
void SG_rook(){
memset(sg_r, 0, sizeof(sg_r));
for(int i=1; i<=1000; i++){
for(int j=1; j<=1000; j++){
if(sg_r[i][j]) continue;
for(int k=j+1; k<=1000; k++) sg_r[i][k]=1;
for(int k=i+1; k<=1000; k++) sg_r[k][j]=1;
}
}
}
int judge_knight(int x, int y){
if(x==1 && y==1) return 0;
if(x==1 || y==1) return -1;
if(sg_kn[x-1][y-2]==0 || sg_kn[x-2][y-1]==0) return 1;
if(sg_kn[x-1][y-2]==-1 || sg_kn[x-2][y-1]==-1) return -1;
return 0;
}
void SG_knight(){
for(int i=0; i<=1000; i++) sg_kn[i][0]=-1;
for(int j=0; j<=1000; j++) sg_kn[0][j]=-1;
for(int i=1; i<=1000; i++){
for(int j=1; j<=1000; j++){
sg_kn[i][j]=judge_knight(i, j);
}
}
}
void SG_queen(){
memset(sg_q, 0, sizeof(sg_q));
for(int i=1; i<=1000; i++){
for(int j=1; j<=1000; j++){
if(sg_q[i][j]) continue;
for(int k=j+1; k<=1000; k++) sg_q[i][k]=1;
for(int k=i+1; k<=1000; k++) sg_q[k][j]=1;
for(int k=1; i+k<=1000&&j+k<=1000; k++) sg_q[i+k][j+k]=1;
}
}
}
int main(){
int T, t, n, m;
SG_king();
SG_rook();
SG_knight();
SG_queen();
scanf("%d", &T);
while(T--){
scanf("%d%d%d", &t, &n, &m);
if(t==1){
if(sg_k[n][m]) printf("B\n");
else printf("G\n");
}
if(t==2){
if(sg_r[n][m]) printf("B\n");
else printf("G\n");
}
if(t==3){
if(sg_kn[n][m]==1) printf("B\n");
else if(sg_kn[n][m]==0) printf("G\n");
else printf("D\n");
}
if(t==4){
if(sg_q[n][m]) printf("B\n");
else printf("G\n");
}
}
return 0;
}