bzoj3106: [cqoi2013]棋盘游戏

题目链接

bzoj3106: [cqoi2013]棋盘游戏

题解

n = 20
显然当A不能一步吃掉B时,A必输
那么就是stepA - stepB
A想步数多,B想步数少
对抗搜索
可以证明B一定能在n * 4步以内获胜
记忆化一下

代码

/*bzoj 3106*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#define INF 0x3f3f3f3f
inline int read() {
	int x = 0,f = 1;
	char c = getchar();
	while(c < '0' || c > '9') {if(c == '-')f = -1;c = getchar();}
	while(c <= '9' && c >= '0') x = x * 10 + c - '0', c = getchar();
	return x * f;
}
const int maxn = 21;
int n;
int s[2][70][maxn][maxn][maxn][maxn];
int fs1[5] = {1,0,-1,0,1}; 
int fs2[5] = {2,0,-2,0,2};
inline bool judge(int x,int y) { return (x >= 1 && x <= n && y >= 1 && y <= n) ? true : false;} 
int dfs(int nxt,int step,int a,int b,int c,int d) { 
	if(step > n * 3) return INF;  
	if(a == c && b == d) return nxt ? INF : 0; 
	if(s[nxt][step][a][b][c][d]) return s[nxt][step][a][b][c][d]; 
	int ret = nxt ? INF : 0;
	if(nxt) { 
		for(int i = 0;i < 4;++ i) { 
			int tx = c + fs1[i],ty = d + fs1[i + 1];
			if(judge(tx,ty)) ret = std::min(ret,dfs(nxt ^ 1,step + 1,a,b,tx,ty)) ; 
			tx = c + fs2[i],ty = d + fs2[i + 1];
			if(judge(tx,ty)) ret = std::min(ret,dfs(nxt ^ 1,step + 1,a,b,tx,ty)) ; 
		} 
	} 
	else 
		for(int i = 0;i < 4;++ i) { 
			int tx = a + fs1[i],ty = b + fs1[i + 1]; 
			if(judge(tx,ty)) ret = std::max(ret,dfs(nxt ^ 1,step + 1,tx,ty,c,d)); 
		} 
	return s[nxt][step][a][b][c][d] = ++ret; 
} 
int main() { 
	int a,b,c,d;
	n = read(),a = read(),b = read(),c = read(),d = read();  
	if(abs(a - c) + abs(b - d) == 1) printf("WHITE 1\n"); 	
	else printf("BLACK %d\n",dfs(0,0,a,b,c,d)); 
	return 0; 
}

posted @ 2018-04-30 09:13  zzzzx  阅读(317)  评论(0编辑  收藏  举报