bzoj3106 [cqoi2013]棋盘游戏

Description

一个n*n(n>=2)棋盘上有黑白棋子各一枚。游戏者A和B轮流移动棋子,A先走。
l         A的移动规则:只能移动白棋子。可以往上下左右四个方向之一移动一格。
l         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

 

正解:对抗搜索。

首先如果先手不能在第一步就赢,那么他就必输,因为后手可以把先手围在角落里。

然后设$f[0/1][y][a][b][c][d]$表示当前是先手/后手,总共走了几步,先手在$(a,b)$,后手在$(c,d)$,直接按照对抗搜索的方法转移就行。

以前没有写过对抗搜索,还是挂一个链接:博弈基础——极大极小搜索

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define inf (1<<30)
 6 
 7 using namespace std;
 8 
 9 const int d1[8]={1,0,-1,0,2,0,-2,0};
10 const int d2[8]={0,1,0,-1,0,2,0,-2};
11 
12 int f[2][65][21][21][21][21],n,a,b,c,d;
13 
14 il int gi(){
15   RG int x=0,q=1; RG char ch=getchar();
16   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
17   if (ch=='-') q=-1,ch=getchar();
18   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
19   return q*x;
20 }
21 
22 il int dfs(RG int x,RG int y,RG int a,RG int b,RG int c,RG int d){
23   if (y>3*n) return inf; if (a==c && b==d) return x?inf:0;
24   if (f[x][y][a][b][c][d]) return f[x][y][a][b][c][d]; RG int res;
25   if (x){
26     res=inf;
27     for (RG int i=0,X,Y;i<8;++i){
28       X=c+d1[i],Y=d+d2[i];
29       if (X>=1 && X<=n && Y>=1 && Y<=n)
30     res=min(res,dfs(x^1,y+1,a,b,X,Y));
31     }
32   } else{
33     res=0;
34     for (RG int i=0,X,Y;i<4;++i){
35       X=a+d1[i],Y=b+d2[i];
36       if (X>=1 && X<=n && Y>=1 && Y<=n)
37     res=max(res,dfs(x^1,y+1,X,Y,c,d));
38     }
39   }
40   return f[x][y][a][b][c][d]=res+1;
41 }
42 
43 int main(){
44 #ifndef ONLINE_JUDGE
45   freopen("chess.in","r",stdin);
46   freopen("chess.out","w",stdout);
47 #endif
48   n=gi(),a=gi(),b=gi(),c=gi(),d=gi();
49   if (abs(a-c)+abs(b-d)==1) puts("WHITE 1");
50   else printf("BLACK %d\n",dfs(0,0,a,b,c,d));
51   return 0;
52 }

 

posted @ 2017-12-31 19:42  wfj_2048  阅读(278)  评论(0编辑  收藏  举报