题解 洛谷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
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<=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;
}

你可能感兴趣的:(题解 洛谷P5380 【[THUPC2019]鸭棋】)