题解 洛谷P5380 【[THUPC2019]鸭棋】
就是一道大模拟。
首先,来解释一下复杂的题意:
给你一些棋子,每个棋都有不同的走法,开局是回归原位。
接下来,题目会给你一个虚拟的走子操作(注意不一定真实),你所需要判断当前操作是否正确。若不正确,输出\(Invalid command\)。否则,输出当前操作的棋子,其淘汰掉的棋子,是否将军,对局是否结束这四个信息。
\(OK,\)那我们一步一步来。
走子规则应该不用多讲了吧,我们可以用数组来存储。只是,鸭的走法可能有一部分人看不懂,其实就是马的进化版呀!假设我们说马走日走的是一个\(1 \times 2\),那么鸭子其实就是走的\(2 \times 3\),其本质是一样的。只是,每个棋子都不能超出棋盘,而且其中的马,象,和鸭还要考虑憋腿的情况。
当然还要特别注意的是车的走法,车可以横冲直撞,所以我们不必用数组存,到时候直接向四面八方走即可。
好,走子规则没什么问题,我们来看每一次的操作。
一开始的棋盘是初始化的,我们用\(a[i][j]\)表示第\(i\)行\(j\)列的棋子\((1\)~\(7)\),用\(h[i][j]\)表示的第\(i\)行\(j\)列的棋子的颜色。(红表示\(1\),蓝表示\(2\))。
然后来看,对于每个操作,我们把棋子的出发点做起点,棋子的到达点叫做落点。那么,如果起点和落点有任何一个不存在,也就是超出棋盘范围,说明操作一定是不合法的,所以\(pass\)掉。
接着,我们再用一个\(color\)变量维护当前应该是哪一方走棋。显而易见的,起点一定是本方的,而落点不能是本方的。如果不满足也说明当前操作不合法。
好了,下面我们可以来暴力大模拟了。
大致可以分成几类:
\(step1:\)判断当前是哪枚棋子。不同的棋子,它的走法也不同,所以我们要分类讨论。
\(step2:\)对于当前棋子,我们遍历它的所有走法。寻找是否有落点与题目中给出的落点吻合。如果吻合,判断当前落点是否有棋子,如果没有,就判断它是什么棋子。然后再对当前点进行移动。最后别忘记,如果一遍扫下来都没有和给出的落点相吻合,那么输出\(Invalid command\)。
\(step3:\)看当前局面是否存在将军。我们可以分别判断,无疑也就两种情况:
是否有红棋可以淘汰蓝将
是否有蓝棋可以淘汰红将
如果满足其一,说明存在将军局面,输出\(yes\),否则输出\(no\)。
\(step4:\)看当前局面中是否还存在两个王,如果只剩一个,说明另外一个已经被淘汰了,也就是游戏已经结束。
【特别注意】
如果当前操作不合法,那么本来哪方走棋,接下来还是哪方走棋,不用变化。
如果游戏已经结束,后面的操作就不用执行了,直接输出\(Invalid command\)即可。
\(Code:\)
#include<bits/stdc++.h>
using namespace std;
inline int read(){
register int s=0,f=1;
register char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f*=-1;ch=getchar();}
while(isdigit(ch))s=(s<<1)+(s<<3)+(ch^48),ch=getchar();
return s*f;
}
const int captain[20][5]={
{0,1},{1,0},{0,-1},{-1,0}
};
const int guard[20][5]={
{1,1},{1,-1},{-1,1},{-1,-1}
};
const int elephant[20][5]={
{2,-2},{-2,2},{2,2},{-2,-2}
};
const int Elephant[20][5]={
{1,-1},{-1,1},{1,1},{-1,-1}
};
const int horse[20][5]={
{2,-1},{2,1},{1,2},{-1,2},{-2,1},{-2,-1},{-1,-2},{1,-2}
};
const int Horse[20][5]={
{1,0},{1,0},{0,1},{0,1},{-1,0},{-1,0},{0,-1},{0,-1}
};
const int duck[20][5]={
{3,2},{-3,2},{2,3},{2,-3},{3,-2},{-3,-2},{-2,3},{-2,-3}
};
const int Duck[20][5]={
{1,0},{-1,0},{0,1},{0,-1},{1,0},{-1,0},{0,1},{0,-1},
{2,1},{-2,1},{1,2},{1,-2},{2,-1},{-2,-1},{-1,2},{-1,-2}
};
const int soldier[20][5]={
{0,1},{1,0},{0,-1},{-1,0},{1,1},{-1,-1},{1,-1},{-1,1}
};
//每个子的走法如上
int color,End,flg;
int a[20][20],h[20][20];
string f[10];
void Clean(){
f[1]="captain";f[2]="guard";
f[3]="elephant";f[4]="horse";
f[5]="car";f[6]="duck";f[7]="soldier";//数字对应棋子
a[1][1]=a[1][9]=5,h[1][1]=h[1][9]=1;
a[1][2]=a[1][8]=4,h[1][2]=h[1][8]=1;
a[1][3]=a[1][7]=3,h[1][3]=h[1][7]=1;
a[1][4]=a[1][6]=2,h[1][4]=h[1][6]=1;
a[1][5]=1,h[1][5]=1;
a[3][1]=a[3][9]=6,h[3][1]=h[3][9]=1;
a[4][1]=a[4][3]=a[4][5]=a[4][7]=a[4][9]=7;
h[4][1]=h[4][3]=h[4][5]=h[4][7]=h[4][9]=1;
a[10][1]=a[10][9]=5,h[10][1]=h[10][9]=2;
a[10][2]=a[10][8]=4,h[10][2]=h[10][8]=2;
a[10][3]=a[10][7]=3,h[10][3]=h[10][7]=2;
a[10][4]=a[10][6]=2,h[10][4]=h[10][6]=2;
a[10][5]=1,h[10][5]=2;
a[8][1]=a[8][9]=6,h[8][1]=h[8][9]=2;
a[7][1]=a[7][3]=a[7][5]=a[7][7]=a[7][9]=7;
h[7][1]=h[7][3]=h[7][5]=h[7][7]=h[7][9]=2; //初始化棋盘
}
bool bianjie(int x,int y){//边界判断
if(x>=1&&x<=10&&y>=1&&y<=9)return true;
return false;
}
void Jiangjun(int x){//将军判断,x表示将哪一方的军
for(int i=1;i<=10;i++){
for(int j=1;j<=9;j++){
if(h[i][j]==x)continue;//当前点必须是对方的
if(a[i][j]==1){//开始模拟每一个棋子
for(int k=0;k<4;k++){
int tx=i+captain[k][0];
int ty=j+captain[k][1];
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}else if(a[i][j]==2){
for(int k=0;k<4;k++){
int tx=i+guard[k][0];
int ty=j+guard[k][1];
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}else if(a[i][j]==3){
for(int k=0;k<4;k++){
int tx=i+elephant[k][0];
int ty=j+elephant[k][1];
int px=i+Elephant[k][0];
int py=j+Elephant[k][1];
if(h[px][py])continue;
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}else if(a[i][j]==4){
for(int k=0;k<8;k++){
int tx=i+horse[k][0];
int ty=j+horse[k][1];
int px=i+Horse[k][0];
int py=j+Horse[k][1];
if(h[px][py])continue;
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}else if(a[i][j]==5){
for(int k=i+1;k<=10;k++){
if(h[k][j]==x&&a[k][j]==1){
flg=1;
return;
}
if(h[k][j])break;
}
for(int k=i-1;k>=1;k--){
if(h[k][j]==x&&a[k][j]==1){
flg=1;
return;
}
if(h[k][j])break;
}
for(int k=j+1;k<=9;k++){
if(h[i][k]==x&&a[i][k]==1){
flg=1;
return;
}
if(h[i][k])break;
}
for(int k=j-1;k>=1;k--){
if(h[i][k]==x&&a[i][k]==1){
flg=1;
return;
}
if(h[i][k])break;
}
}else if(a[i][j]==6){
for(int k=0;k<8;k++){
int tx=i+duck[k][0];
int ty=j+duck[k][1];
int px1=i+Duck[k][0],px2=i+Duck[k+8][0];
int py1=j+Duck[k][1],py2=j+Duck[k+8][1];
if(h[px1][py1]||h[px2][py2])continue;
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}else if(a[i][j]==7){
for(int k=0;k<8;k++){
int tx=i+soldier[k][0];
int ty=j+soldier[k][1];
if(h[tx][ty]==x&&a[tx][ty]==1){
flg=1;
return;
}
}
}
}
}
}
void jiangjun(){
Jiangjun(1),Jiangjun(2);//红方是否被将军?蓝方是否被将军?
if(flg==1)cout<<"yes;";
else cout<<"no;";
flg=0;//注意清0哦~
}
bool checkcaptain(){
int tot=0;
for(int i=1;i<=10;i++){
for(int j=1;j<=9;j++){
if(a[i][j]==1)tot++;
}
}
return tot==2;
}
void printst(int x,int y){
if(h[x][y]==1)cout<<"red ";
else cout<<"blue ";
cout<<f[a[x][y]]<<";";
}
void check1(int x,int y,int dx,int dy){
for(int i=0;i<4;i++){
int tx=x+captain[i][0];
int ty=y+captain[i][1];//下一个点
if(tx==dx&&ty==dy){
printst(x,y);//输出当前点
if(h[tx][ty]==2-color%2)printst(tx,ty);//输出下一个点
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();//判断是否存在将军局面
if(checkcaptain())cout<<"no"<<"\n";//结束了吗?两个王还在吗?
else cout<<"yes"<<"\n",End=1;
color++;//注意换成对方走棋
return;
}
}
cout<<"Invalid command"<<"\n";
}
void check2(int x,int y,int dx,int dy){
for(int i=0;i<4;i++){
int tx=x+guard[i][0];
int ty=y+guard[i][1];
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
}
cout<<"Invalid command"<<"\n";
}
void check3(int x,int y,int dx,int dy){
for(int i=0;i<4;i++){
int tx=x+elephant[i][0];
int ty=y+elephant[i][1];
int px=x+Elephant[i][0];
int py=y+Elephant[i][1];
if(h[px][py])continue;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
}
cout<<"Invalid command"<<"\n";
}
void check4(int x,int y,int dx,int dy){
for(int i=0;i<8;i++){
int tx=x+horse[i][0];
int ty=y+horse[i][1];
int px=x+Horse[i][0];
int py=y+Horse[i][1];
if(h[px][py])continue;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
}
cout<<"Invalid command"<<"\n";
}
void check5(int x,int y,int dx,int dy){
for(int i=x+1;i<=10;i++){//车向四个方向拓展,注意可不能挡它QAQ
int tx=i,ty=y;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
if(h[tx][ty])break;
}
for(int i=x-1;i>=1;i--){
int tx=i,ty=y;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
if(h[tx][ty])break;
}
for(int i=y+1;y<=9;i++){
int tx=x,ty=i;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
if(h[tx][ty])break;
}
for(int i=y-1;y>=1;i--){
int tx=x,ty=i;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
if(h[tx][ty])break;
}
cout<<"Invalid command"<<"\n";
}
void check6(int x,int y,int dx,int dy){
for(int i=0;i<8;i++){
int tx=x+duck[i][0];
int ty=y+duck[i][1];
int px1=x+Duck[i][0],px2=x+Duck[i+8][0];
int py1=y+Duck[i][1],py2=y+Duck[i+8][1];
if(h[px1][py1]||h[px2][py2])continue;
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
}
cout<<"Invalid command"<<"\n";
}
void check7(int x,int y,int dx,int dy){
for(int i=0;i<8;i++){
int tx=x+soldier[i][0];
int ty=y+soldier[i][1];
if(tx==dx&&ty==dy){
printst(x,y);
if(h[tx][ty]==2-color%2)printst(tx,ty);
else cout<<"NA;";
a[tx][ty]=a[x][y],h[tx][ty]=h[x][y];
a[x][y]=h[x][y]=0;
jiangjun();
if(checkcaptain())cout<<"no"<<"\n";
else cout<<"yes"<<"\n",End=1;
color++;
return;
}
}
cout<<"Invalid command"<<"\n";
}
int main(){
Clean();
int T=read();
while(T--){
int xs=read()+1,ys=read()+1,xt=read()+1,yt=read()+1;
if((!bianjie(xs,ys))||(!bianjie(xt,yt))||End){//判断程序结束或是起点和落点出了边界
cout<<"Invalid command"<<"\n";
continue;
}
if(color%2==0){//判断当前哪一方走棋
if(h[xs][ys]!=1||h[xt][yt]==1){
cout<<"Invalid command"<<"\n";
continue;
}
}else{
if(h[xs][ys]!=2||h[xt][yt]==2){
cout<<"Invalid command"<<"\n";
continue;
}
}
if(a[xs][ys]==1)check1(xs,ys,xt,yt);
else if(a[xs][ys]==2)check2(xs,ys,xt,yt);
else if(a[xs][ys]==3)check3(xs,ys,xt,yt);
else if(a[xs][ys]==4)check4(xs,ys,xt,yt);
else if(a[xs][ys]==5)check5(xs,ys,xt,yt);
else if(a[xs][ys]==6)check6(xs,ys,xt,yt);
else if(a[xs][ys]==7)check7(xs,ys,xt,yt);//分类讨论每一个点
}
return 0;
}
\(\operatorname{Update}\) \(\operatorname{on}\) \(\operatorname{2019.08.03}\)
题解 洛谷P5380 【[THUPC2019]鸭棋】的更多相关文章
- 【洛谷】P1541 乌龟棋(四维背包dp)
题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行N个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第N格是终点,游戏要求玩家控制一个乌龟棋子从起 ...
- 【题解】洛谷P1541 [NOIP2010TG] 乌龟棋(类似背包的DP)
题目来源:洛谷P1541 思路 类似背包的题 总之就是四种卡牌取的先后顺序不同导致的最终ans不同 所以我们用一个四维数组每一维分别表示第几种取了几张的最大分数 然后就是简单DP解决 代码 #incl ...
- 题解 洛谷P5018【对称二叉树】(noip2018T4)
\(noip2018\) \(T4\)题解 其实呢,我是觉得这题比\(T3\)水到不知道哪里去了 毕竟我比较菜,不大会\(dp\) 好了开始讲正事 这题其实考察的其实就是选手对D(大)F(法)S(师) ...
- 题解 洛谷 P3396 【哈希冲突】(根号分治)
根号分治 前言 本题是一道讲解根号分治思想的论文题(然鹅我并没有找到论文),正 如论文中所说,根号算法--不仅是分块,根号分治利用的思想和分块像 似却又不同,某一篇洛谷日报中说过,分块算法实质上是一种 ...
- 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)
题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...
- 题解-洛谷P4229 某位歌姬的故事
题面 洛谷P4229 某位歌姬的故事 \(T\) 组测试数据.有 \(n\) 个音节,每个音节 \(h_i\in[1,A]\),还有 \(m\) 个限制 \((l_i,r_i,g_i)\) 表示 \( ...
- 题解-洛谷P4724 【模板】三维凸包
洛谷P4724 [模板]三维凸包 给出空间中 \(n\) 个点 \(p_i\),求凸包表面积. 数据范围:\(1\le n\le 2000\). 这篇题解因为是世界上最逊的人写的,所以也会有求凸包体积 ...
- 题解-洛谷P4859 已经没有什么好害怕的了
洛谷P4859 已经没有什么好害怕的了 给定 \(n\) 和 \(k\),\(n\) 个糖果能量 \(a_i\) 和 \(n\) 个药片能量 \(b_i\),每个 \(a_i\) 和 \(b_i\) ...
- 题解-洛谷P5217 贫穷
洛谷P5217 贫穷 给定长度为 \(n\) 的初始文本 \(s\),有 \(m\) 个如下操作: \(\texttt{I x c}\),在第 \(x\) 个字母后面插入一个 \(c\). \(\te ...
随机推荐
- 乐橙平台大华监控Android端实时预览播放
一.初始化 首先我们需要到乐橙开放平台下载android对应的开发包,将sdk中提供的jar和so文件添加到项目中: 二.获取监控列表 监控列表我们是通过从自家后台服务器中获取的,这个自己根据需要调整 ...
- Centos7修改profile错误的解救方案
在改profile的时候,改出问题了,除了cd以外的命令基本都不能用了.使用root用户执行: # export PATH=/usr/bin:/usr/sbin:/bin:/sbin:/usr/X11 ...
- Docker的基础教程(基于CentOS)
1.查看版本 Docker 要求 CentOS 系统的内核版本高于 3.10 ,查看本页面的前提条件来验证你的CentOS 版本是否支持 Docker . 通过 uname -r 命令查看你当前的内核 ...
- 查看LINUX进程内存占用情况及启动时间
可以直接使用top命令后,查看%MEM的内容.可以选择按进程查看或者按用户查看,如想查看oracle用户的进程内存使用情况的话可以使用如下的命令: (1) top top命令是Linux下常用的性能分 ...
- [转帖]使用fastdfs搭建文件管理系统
使用fastdfs搭建文件管理系统 https://www.jianshu.com/p/4e80069c84d3 今天同事说他们的系统用到了这个分布式文件管理系统. 一.FastDFS介绍 FastD ...
- [转帖]Introduction to Linux monitoring and alerting
Introduction to Linux monitoring and alerting https://www.redhat.com/sysadmin/linux-monitoring-and-a ...
- 设置Kafka集群的方法
1.目标 今天,在这篇Kafka文章中,我们将看到Kafka Cluster Setup.这个Kafka集群教程为我们提供了一些设置Kafka集群的简单步骤.简而言之,为了实现Kafka服务的高可用性 ...
- C++容器简介1—stack
一.简介 stack是一种容器适配器(STL的容器分为顺序容器和关联容器,容器适配器),被设计来用于操作先进后出(FILO)结构的情景,在这种情况下, 元素的插入和删除都只能在容器的尾部进行. sta ...
- ORACLE数据库实现自增的两种方式
Mysql数据库因为其有自动+1,故一般我们不需要花费太多时间,直接用关键字auto_increment即可,但是Oracle不行,它没有自动增长机制.顾我们需要自己去实现.一般有两种方式,但是这两种 ...
- The Day Two 找到一个具有最大和的连续子数组,返回其最大和
""" 给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和. 示例: 输入: [-2,1,-3,4,-1,2,1,-5, ...