[CQOI2013]棋盘游戏
Description
一个n*n(n>=2)棋盘上有黑白棋子各一枚。游戏者A和B轮流移动棋子,A先走。
A的移动规则:只能移动白棋子。可以往上下左右四个方向之一移动一格。
B的移动规则:只能移动黑棋子。可以往上下左右四个方向之一移动一格或者两格。
和通常的“吃子”规则一样,当某游戏者把自己的棋子移动到对方棋子所在的格子时,他就赢了。两个游戏者都很聪明,当可以获胜时会尽快获胜,只能输掉的时候会尽量拖延时间。你的任务是判断谁会赢,需要多少回合。
比如n=2,白棋子在(1,1),黑棋子在(2,2),那么虽然A有两种走法,第二个回合B总能取胜。
Input
输入仅一行,包含五个整数n, r1, c1, r2, c2,即棋盘大小和棋子位置。白色棋子在(r1,c1),黑色棋子在(r2,c2)(1<=r1,c1,r2,c2<=n)。黑白棋子的位置保证不相同。
Output
输出仅一行,即游戏结果。如果A获胜,输出WHITE x;如果B获胜,输出BLACK x;如果二者都没有必胜策略,输出DRAW。
Sample Input
2 1 1 2 2
Sample Output
BLACK 2
HINT
n<=20
首先白子如果第一回合没吃掉黑子,那他就凉了
因为黑子总是能占据主动
因为可以黑棋走的距离比白棋大,黑棋可以下一步吃掉白棋,也可以下一步离开白棋的吃子范围
因为黑白子曼哈顿距离最大2×n
每一轮行动黑棋都可以接近至少1的距离(不会是0,因为没有意义),所以最多只有4×n轮
然后就是Y&*^*&%*
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 using namespace std; 7 int dx[8]={0,1,0,-1,0,2,0,-2}; 8 int dy[8]={1,0,-1,0,2,0,-2,0}; 9 int f[2][81][21][21][21][21],inf=2e9,n; 10 int dfs(int x,int y,int x1,int y1,int x2,int y2) 11 {int i; 12 int res; 13 if (y>3*n) return inf; 14 if (x1==x2&&y1==y2) 15 { 16 if (x==0) return 0; 17 else return inf; 18 } 19 if (f[x][y][x1][y1][x2][y2]) return f[x][y][x1][y1][x2][y2]; 20 if (!x) 21 { 22 res=0; 23 for (i=0;i<4;i++) 24 { 25 int xx=x1+dx[i]; 26 int yy=y1+dy[i]; 27 if (xx>=1&&yy>=1&&xx<=n&&yy<=n) 28 { 29 res=max(res,dfs(x^1,y+1,xx,yy,x2,y2)); 30 } 31 } 32 } 33 else 34 { 35 res=inf; 36 for (i=0;i<8;i++) 37 { 38 int xx=x2+dx[i]; 39 int yy=y2+dy[i]; 40 if (xx>=1&&yy>=1&&xx<=n&&yy<=n) 41 { 42 res=min(res,dfs(x^1,y+1,x1,y1,xx,yy)); 43 } 44 } 45 } 46 f[x][y][x1][y1][x2][y2]=res+1; 47 return res+1; 48 } 49 int main() 50 {int v,x1,y1,x2,y2; 51 cin>>n>>x1>>y1>>x2>>y2; 52 if (abs(x1-x2)+abs(y1-y2)<=1) printf("WHITE 1\n"); 53 else 54 { 55 v=dfs(0,0,x1,y1,x2,y2); 56 if (v>inf) printf("DRAW\n"); 57 else printf("BLACK %d\n",v); 58 } 59 }