题解 洛谷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;
}
标签:洛谷,tx,ty,int,题解,落点,THUPC2019,棋子,&& 来源: https://www.cnblogs.com/Agonim/p/12080793.html