【BZOJ3106】[CQOI2013] 棋盘游戏(对抗搜索)
大致题意: 在一张\(n*n\)的棋盘上有一枚黑棋子和一枚白棋子。白棋子先移动,然后是黑棋子。白棋子每次可以向上下左右四个方向中任一方向移动一步,黑棋子每次则可以向上下左右四个方向中任一方向移动一至二步。当某游戏者把自己的棋子移动到对方棋子所在的格子时,他就赢了。两个游戏者都很聪明,可以获胜时会尽快获胜,必输时会尽量拖延时间。试判断谁会赢,需要多少回合。
对抗搜索
这道题的做法应该是对抗搜索。
一波简单的分析
我们先来对题目进行一波简单的分析。
不难发现,因为黑棋每次能走的步数大于白棋每次能走的步数,所以除非白棋第一步就吃掉黑棋,否则白棋必输。
既然这样,我们只需特判白棋获胜的情况,然后题目就转换成了求黑棋追上白棋所需的时间。
这样一来,就变成了一道较简单的对抗搜索题了。
直接用记忆化优化即可(当然,理论上来讲\(Alpha-Beta\)剪枝也可以做,但我没去试过)。
代码
#include<bits/stdc++.h>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)<(y)?(x):(y))
#define abs(x) ((x)<0?-(x):(x))
#define LL long long
#define ull unsigned long long
#define swap(x,y) (x^=y,y^=x,x^=y)
#define Fsize 100000
#define tc() (FinNow==FinEnd&&(FinEnd=(FinNow=Fin)+fread(Fin,1,Fsize,stdin),FinNow==FinEnd)?EOF:*FinNow++)
#define pc(ch) (putchar(ch))
#define N 20
int OutputTop=0;char Fin[Fsize],*FinNow=Fin,*FinEnd=Fin,OutputStack[Fsize];
using namespace std;
int n,X1,Y1,X2,Y2,res[N+1][N+1][N+1][N+1][2][3*N+1];
inline void read(int &x)
{
x=0;static char ch;
while(!isdigit(ch=tc()));
while(x=(x<<3)+(x<<1)+ch-48,isdigit(ch=tc()));
}
inline void write(int x)
{
if(!x) return (void)pc('0');
while(x) OutputStack[++OutputTop]=x%10+48,x/=10;
while(OutputTop) pc(OutputStack[OutputTop]),--OutputTop;
}
inline int dfs(int X1,int Y1,int X2,int Y2,int Which,int Step)//对抗搜索
{
if(Step>3*n) return 1e9;//深度限制,以防无限制地搜索下去(可以保证最终的答案≤3n)
if(res[X1][Y1][X2][Y2][Which][Step]) return res[X1][Y1][X2][Y2][Which][Step];//如果已经访问当前状态,就返回上次求解出的答案
if(X1==X2&&Y1==Y2) return Which?1e9:0;//如果已经重合了,就退出函数
register int i,t,ans=Which?1e9:0;
Which^=1,++Step;//更新Which和Step为下一个状态,以避免不断地运算
if(Which)//如果下一个轮黑棋操作,即当前为白棋操作
{
if(X1>1) t=dfs(X1-1,Y1,X2,Y2,Which,Step),ans=max(ans,t);
if(X1<n) t=dfs(X1+1,Y1,X2,Y2,Which,Step),ans=max(ans,t);
if(Y1>1) t=dfs(X1,Y1-1,X2,Y2,Which,Step),ans=max(ans,t);
if(Y1<n) t=dfs(X1,Y1+1,X2,Y2,Which,Step),ans=max(ans,t);
}
else//如果当前为黑棋操作
{
if(X2>1) t=dfs(X1,Y1,X2-1,Y2,Which,Step),ans=min(ans,t);
if(X2>2) t=dfs(X1,Y1,X2-2,Y2,Which,Step),ans=min(ans,t);
if(X2<=n-1) t=dfs(X1,Y1,X2+1,Y2,Which,Step),ans=min(ans,t);
if(X2<=n-2) t=dfs(X1,Y1,X2+2,Y2,Which,Step),ans=min(ans,t);
if(Y2>1) t=dfs(X1,Y1,X2,Y2-1,Which,Step),ans=min(ans,t);
if(Y2>2) t=dfs(X1,Y1,X2,Y2-2,Which,Step),ans=min(ans,t);
if(Y2<=n-1) t=dfs(X1,Y1,X2,Y2+1,Which,Step),ans=min(ans,t);
if(Y2<=n-2) t=dfs(X1,Y1,X2,Y2+2,Which,Step),ans=min(ans,t);
}
return res[X1][Y1][X2][Y2][Which^1][Step-1]=ans+1;
}
int main()
{
read(n),read(X1),read(Y1),read(X2),read(Y2);
if(abs(X1-X2)+abs(Y1-Y2)<=1) return puts("WHITE 1"),0;//特判白棋获胜的情况
return pc('B'),pc('L'),pc('A'),pc('C'),pc('K'),pc(' '),write(dfs(X1,Y1,X2,Y2,0,1)),0;
}
【BZOJ3106】[CQOI2013] 棋盘游戏(对抗搜索)的更多相关文章
- [bzoj3106][cqoi2013][棋盘游戏] (对抗搜索+博弈论)
Description 一个n*n(n>=2)棋盘上有黑白棋子各一枚.游戏者A和B轮流移动棋子,A先走. l A的移动规则:只能移动白棋子.可以往上下左右四个方向之一移动一格. ...
- bzoj3106 [cqoi2013]棋盘游戏
Description 一个n*n(n>=2)棋盘上有黑白棋子各一枚.游戏者A和B轮流移动棋子,A先走. l A的移动规则:只能移动白棋子.可以往上下左右四个方向之一移动一格. ...
- bzoj千题计划200:bzoj3106: [cqoi2013]棋盘游戏
http://www.lydsy.com/JudgeOnline/problem.php?id=3106 白棋如果第一步不能赢,那么一定输 因为可以黑棋走的距离比白棋大,黑棋可以下一步吃掉白棋,也可以 ...
- BZOJ 3106: [cqoi2013]棋盘游戏(对抗搜索)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3106 对抗搜索,f[x][y][a][b][c][d]表示当前谁走,走了几步,及位置. (因为 ...
- 【BZOJ 3106】 3106: [cqoi2013]棋盘游戏 (对抗搜索)
3106: [cqoi2013]棋盘游戏 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 544 Solved: 233 Description 一个 ...
- 博弈论经典算法(一)——对抗搜索与Alpha-Beta剪枝
前言 在一些复杂的博弈论题目中,每一轮操作都可能有许多决策,于是就会形成一棵庞大的博弈树. 而有一些博弈论题没有什么规律,针对这样的问题,我们就需要用一些十分玄学的算法. 例如对抗搜索. 对抗搜索简介 ...
- 3106: [cqoi2013]棋盘游戏
3106: [cqoi2013]棋盘游戏 链接 分析: 极大极小搜索 + 记忆化. 代码 #include<bits/stdc++.h> using namespace std; type ...
- BZOJ.5248.[九省联考2018]一双木棋chess(对抗搜索 记忆化)
BZOJ 洛谷P4363 [Update] 19.2.9 重做了遍,感觉之前写的有点扯= = 首先棋子的放置情况是阶梯状的. 其次,无论已经放棋子的格子上哪些是黑棋子哪些是白棋子,之前得分如何,两人在 ...
- P2962 [USACO09NOV]灯Lights 对抗搜索
\(\color{#0066ff}{题目描述}\) 贝希和她的闺密们在她们的牛棚中玩游戏.但是天不从人愿,突然,牛棚的电源跳闸了,所有的灯都被关闭了.贝希是一个很胆小的女生,在伸手不见拇指的无尽的黑暗 ...
随机推荐
- Codeforces Round #558 (Div. 2)C(计算几何,排列组合,模拟)
#include<bits/stdc++.h>using namespace std;typedef struct{ double k,b;}node;node k[1000007];bo ...
- Linux 常用命令一览
本篇博文讲述系统内核.Bash解释器的关系与作用,如何正确的执行Linux命令以及常见排错方法. 经验丰富的运维人员可以恰当的组合命令与参数,使Linux字符命令更加的灵活且相对减少消耗系统资源. 强 ...
- vue散碎知识点学习
1. vue散碎知识点学习 1.1. 特点 数据渲染/数据同步 组件化/模块化 其他功能路由,ajax,数据流 1.2. Vue.js学习资源 vuejs中文官网:http://cn.vuejs.or ...
- 最长双回文串(模板+dp)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline ll read(){ , f ...
- git教程2-git基础
clone 使用IDE,直接在vcs里,从git checkout,方便. commit commit是提交到本地git仓库,本质是做一次存储快照. 可以多次commit之后,再次push到git服务 ...
- SaltStack自动化安装配置haproxy的Keepalived
keepalived配置安装 什么是vrrp,阿里云不支持组播,所以阿里云上不能配置keepalived,但是它有自己的slb.运维的大忌,在命令行复制粘贴,一般是先复制到文本中查看确认以后salt编 ...
- 【ACM】取石子 - 博弈论
取石子(一) 时间限制:3000 ms | 内存限制:65535 KB 难度:2 描述 一天,TT在寝室闲着无聊,和同寝的人玩起了取石子游戏,而由于条件有限,他/她们是用旺仔小馒头当作石子.游 ...
- Java多线程与并发——生产者与消费者应用案例
多线程的开发中有一个最经典的操作案例,就是生产者-消费者,生产者不断生产产品,消费者不断取走产品. package com.vince; /** * 生产者与消费者案例 * @author Admin ...
- 图片的回显。js
l <tr><td></td> <td> <c:if test="${editVo.pic!=''}"><img ...
- Hystrix核心基础 - 滑动窗口创建过程及demo
前言 RxJava可能有些小伙伴没有听过是什么东西,可能是因为大家平时在做业务需求的时候对异步编程了解得比较少,而RxJava就是这么一个响应式编程框架,RxJava在安卓上面用得非常多,做安卓的朋友 ...