• BZOJ 3106 棋盘游戏


    Description

    一个(n imes n(n le 2))棋盘上有黑白棋子各一枚。游戏者A和B轮流移动棋子,A先走。
    A的移动规则:只能移动白棋子。可以往上下左右四个方向之一移动一格。
    B的移动规则:只能移动黑棋子。可以往上下左右四个方向之一移动一格或者两格。
    和通常的“吃子”规则一样,当某游戏者把自己的棋子移动到对方棋子所在的格子时,他就赢了。两个游戏者都很聪明,当可以获胜时会尽快获胜,只能输掉的时候会尽量拖延时间。你的任务是判断谁会赢,需要多少回合。
    比如(n=2),白棋子在((1,1)),黑棋子在((2,2)),那么虽然A有两种走法,第二个回合B总能取胜。

    Input

    输入仅一行,包含五个整数(n, r_{1}, c_{1}, r_{2}, c_{2}),即棋盘大小和棋子位置。白色棋子在((r_{1},c_{1})),黑色棋子在((r_{2},c_{2})(1 le r_{1},c_{1},r_{2},c_{2} le n))。黑白棋子的位置保证不相同。

    Output

    输出仅一行,即游戏结果。如果A获胜,输出WHITE (x);如果B获胜,输出BLACK (x);如果二者都没有必胜策略,输出DRAW。

    Sample Input

    2 1 1 2 2

    Sample Output

    BLACK 2

    HINT

    (n le 20)

    首先有个结论可以判胜负:
    如果A与B只相差一格,那么A一定获胜;否则B一定获胜。那个平局只是来卖个萌的。(B走的快一些)
    然后就是求合法的步数了,这个是CLB告诉我的极大极小搜索。
    我开始裸搜果断TLE,加了记忆化,果断WA,没怎么打过,怎么调也调不对,最后还是参照了别人的程序长了见识。

    #include<iostream>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    using namespace std;
    
    #define inf (1<<30)
    #define lim (3*n+2)
    #define maxn (25)
    const int xx[] = {0,1,0,-1},yy[] = {1,0,-1,0};
    int n,X1,X2,Y1,Y2,ans; int vis[maxn][maxn][maxn][maxn][maxn*3][2];
    
    inline bool okay(int x,int y) { return x > 0&&x<=n&&y > 0&&y<=n; }
    
    inline int dfs(bool now,int a1,int b1,int a2,int b2,int step)
    {
    	if (step > lim) return inf;
    	if (vis[a1][b1][a2][b2][step][now]) return vis[a1][b1][a2][b2][step][now];
    	else if (a1 == a2&&b1 == b2)
    	{
    		if (now) return inf;
    		return 0;
    	}
    	int ret;
    	if (!now)
    	{
    		ret = 0;
    		for (int i = 0;i < 4;++i)
    			if (okay(a1+xx[i],b1+yy[i]))
    				ret = max(dfs(now^1,a1+xx[i],b1+yy[i],a2,b2,step+1),ret);
    	}
    	else
    	{
    		ret = inf;
    		for (int j = 1;j <= 2;++j)
    			for (int i = 0;i < 4;++i)
    				if (okay(a2+j*xx[i],b2+j*yy[i]))
    					ret = min(dfs(now^1,a1,b1,a2+j*xx[i],b2+j*yy[i],step+1),ret);
    	}
    	return vis[a1][b1][a2][b2][step][now] = ++ret;
    }
    
    int main()
    {
    	freopen("3106.in","r",stdin);
    	freopen("3106.out","w",stdout);
    	scanf("%d %d %d %d %d
    ",&n,&X1,&Y1,&X2,&Y2);
    	if (abs(X1-X2)+abs(Y1-Y2) == 1) printf("WHITE 1");
    	else
    	{
    		printf("BLACK ");
    		printf("%d",dfs(0,X1,Y1,X2,Y2,0));		
    	}
    	fclose(stdin); fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    Network (poj1144)
    C. Hongcow Builds A Nation
    ZYB loves Xor I(hud5269)
    D. Chloe and pleasant prizes
    Game(hdu5218)
    约瑟夫环的递推方法
    Misaki's Kiss again(hdu5175)
    Exploration(hdu5222)
    B. Arpa's weak amphitheater and Mehrdad's valuable Hoses
    C. Arpa's loud Owf and Mehrdad's evil plan
  • 原文地址:https://www.cnblogs.com/mmlz/p/4306236.html
Copyright © 2020-2023  润新知