bzoj3106 [cqoi2013]棋盘游戏 极大极小搜索

Description


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

n<=20

Solution


若A不能一步吃掉B则必不赢,很显然是对抗搜索了
卡一卡连ab剪枝都不用。。。

Code


#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
#define fill(x,t) memset(x,t,sizeof(x))

const int INF=1e9;

int dx[8]={-1,1,0,0,-2,2,0,0};
int dy[8]={0,0,-1,1,0,0,-2,2};
int n,rec[21][21][21][21][65][2];

bool check(int x,int y) {
    return (x>=1&&y>=1&&x<=n&&y<=n);
}

int dfs(int x,int y,int a,int b,int s,bool w) {
    if (s>=n*3) return INF;
    if (x==a&&y==b) return (!w)?(INF):(0);
    if (~rec[x][y][a][b][s][w]) return rec[x][y][a][b][s][w];
    int ret=INF;
    if (w) { ret=0; rep(k,0,3) {
        int tx=x+dx[k],ty=y+dy[k];
        if (check(tx,ty)) {
            ret=std:: max(ret,dfs(tx,ty,a,b,s+1,!w));
        }
    } } else { rep(k,0,7) {
        int tx=a+dx[k],ty=b+dy[k];
        if (check(tx,ty)) {
            ret=std:: min(ret,dfs(x,y,tx,ty,s+1,!w));
        }
    } }
    rec[x][y][a][b][s][w]=ret+1;
    return ret+1;
}

int main(void) { fill(rec,-1);
    int r1,c1,r2,c2; scanf("%d%d%d%d%d",&n,&r1,&c1,&r2,&c2);
    if (abs(r1-r2)+abs(c1-c2)==1) puts("WHITE 1");
    else printf("BLACK %d\n", dfs(r1,c1,r2,c2,0,1));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/jpwang8/article/details/80777551