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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值