1 条题解

  • 0
    @ 2025-8-24 22:10:10

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar Pengsibo
    拼尽全力去创造那明显不可能的奇迹,毕竟这是最后一次了。

    搬运于2025-08-24 22:10:10,当前版本为作者最后更新于2019-11-08 17:08:58,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    距离CSP还有10天整的时候,发现自己的算法能力已经崩溃了,百般无奈之下开刷黑模拟,于是在三天之后有了这篇题解

    我们先整理一下题目大意:

    1、这是一道模拟,模拟一种神奇的棋类游戏

    2、棋盘和棋子题目已给出,记得多看几遍(其中鸭的移动方式更是需要好好理解)

    3、输入是一堆操作,把(a,b)上的棋移到(c,d)上

    4、输出分两种:不合法输出"Invalid command",合法则输出移动的棋,被吃的棋,是否形成将军,游戏是否结束

    题意梳理完毕,那我们开始思索解决这道题的方法

    1、用二维数组存储地图,用数字代替每一种棋(其实用字符也行,但比较麻烦)

    • 我们大可以用1~7分别表示王,士,象,马,车,鸭,兵
    • 因为有红蓝方,我们可以通过十位是否为1来判断是哪一方

    2、移动步骤

    • 看到好多大佬都像搜索那样存储移动,但我觉得太麻烦了,还不如在函数中判断当前棋子是哪一种,再直接枚举移动方式

    3、判断将军

    • 一开始我的想法是将移动函数和将军函数合成一个,因为他们都可以利用棋子的移动判断 (从而减少码量) ,但后来咕了所以拆成了两个

    4、输出结果

    • 输出结果其实不是很复杂,记录该次移动被吃的棋,最后输出就是了

    一道模拟题本来没有什么难度,但是为什么也能排成黑题呢?

    • 有些人说,模拟题考察代码能力啊! 我反对,因为代码能力指明白了算法后把它打出来,而不是单纯的暴力 (像我就只会暴力算法垃圾)

    • 有些人说,模拟题考察人的耐心啊!我半赞成,因为有的模拟题真的是打着打着就不想做了

    • 那模拟题考察什么呢?

    • 我认为啊,模拟题考察人的整理和逻辑 (蒟蒻观点大佬勿喷)

    • 你要同时考虑很多的事情,比如这里需不需要特判,那里需不需要return,最后需不需要换行,中间是否要break等等

    • 所以,我将以蒟蒻的亲身体验,指出本题容易掉坑的一些地方:

    1、 每次移动的的时候记得将原来棋子所在的位置清零,并处理它要去的地方

    2、注意处理红蓝关系的转换,以及棋盘的边界问题(被卡一次)

    3、复制粘贴的时候记得进行彻底的修改,要不然这道题都打完了再去找非常痛苦(被卡三次,总计时间一天)

    4、王被抓了以后判断游戏结束,但同时也要记录是哪个王被抓了(被卡一次)

    5、每一次移动棋子的时候有很多的限制条件,其中马、象、鸭注意撇腿,车注意中间不能有子(马、鸭、车各被卡了一次)

    6、这种大模拟一次写过很难,所以必定调试,注意有一些多余的不该出现的东西要删除(为此CE一次)

    那我们开始分析代码吧:

    inline void init()			//初始化棋盘 
    {
    	mapp[0][4]=1,mapp[9][4]=11;
    	mapp[0][3]=2,mapp[0][5]=2,mapp[9][3]=12,mapp[9][5]=12;
    	mapp[0][2]=3,mapp[0][6]=3,mapp[9][2]=13,mapp[9][6]=13;
    	mapp[0][1]=4,mapp[0][7]=4,mapp[9][1]=14,mapp[9][7]=14;
    	mapp[0][0]=5,mapp[0][8]=5,mapp[9][0]=15,mapp[9][8]=15;
    	mapp[2][0]=6,mapp[2][8]=6,mapp[7][0]=16,mapp[7][8]=16;
    	mapp[3][0]=7,mapp[3][2]=7,mapp[3][4]=7,mapp[3][6]=7,mapp[3][8]=7;
    	mapp[6][0]=17,mapp[6][2]=17,mapp[6][4]=17,mapp[6][6]=17,mapp[6][8]=17;
    }
    

    主函数其实只需包含几个分函数

    int main()
    {
    	init();
    
    	scanf("%d",&Q);
    	
    	for(register int i=1;i<=Q;i++)
    	{
    		scanf("%d%d%d%d",&a,&b,&c,&d);	//读入
    		
    		if(capture) {puts("Invalid command");continue;}	//如果游戏已结束,那后续操作都不合法
    		
    		initmove();	//初始化移动
    		move();		//移动
    	
    		if(flagout) continue;	//如果移动中不合法则继续(输出在函数中判断)
    		
    		check();	//检查是否将军
    		
    		print();
    		
    		if(turn==0) turn=1;	//转换红蓝方
    		else turn=0;
    	}
    	
    	return 0;
    }
    

    初始化:

    inline void initmove()		// 初始化 move() 
    {
    	gai=0;
    	flagout=0;
    	extra=0;
    	capture=0;
    	jiang=0;
    }
    

    移动

    • 关于移动,我打了一张大大的表
    • 在把表放出来之前,先说明几个define
    #define out {flagout=1;puts("Invalid command");return;}
    #define bounce (a>=0&&a<=9&&b>=0&&b<=8&&c>=0&&c<=9&&d>=0&&d<=8)
    

    其中out是如果输入不合法,标记,输出,返回

    bounce是确保起点终点都在边界之内

    if(turn==1) extra=10;	//因为我用十位来判断红蓝方,所以蓝方则加十
    
    • 我们需要判断棋子的落点的子

    • 举个例子,如果落点没有子,那当然可以走

    • 如果红棋的落点为蓝棋,那也可以走

    • 但红棋落点为红棋就不能走

    • 所以:

    bool fang(bool turn)		// 是哪一方在动 & bounce
    {
    	if(turn==0) return (mapp[c][d]==0||mapp[c][d]>10);
    	else return (mapp[c][d]==0||mapp[c][d]<10);
    }
    
    
    • 棋子落地之后我们要判断有无棋子被吃:
    void lose(int c,int d)		//判断吞兵 
    {
    	if(mapp[c][d]==1) capture=1,gai=1;			//王被吃了标记
    	else if(mapp[c][d]==11) capture=2,gai=11;
    	else if(mapp[c][d]>10) gai=mapp[c][d],lan--;	//标记被吃的棋
    	else if(mapp[c][d]>0) gai=mapp[c][d],hong--;	//hong和lan用来计数,但发现其实没有什么用
    }
    
    • 最后我们要把棋子放过去
    void exchange(int e,int extra)
    {
    	mapp[a][b]=0,mapp[c][d]=e+extra;
    	which=e+extra;
    }
    

    该放表了

    inline void move()
    {
    	//条件 :符合该棋的移动 路上||终点无棋 终点敌方? 没越界
    	
    	if(turn==1) extra=10;
    	
    	if(mapp[a][b]==1+extra)
    	{
    		if(bounce==0) out		//前面提到 边界
    		if(c-a==1&&b==d&&fang(turn)) 	{lose(c,d);exchange(1,extra);return;}	//符合移动规则和移动方,则判断吃子和移动
    		if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==2+extra)
    	{
    		if(bounce==0) out
    		if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==3+extra)
    	{
    		if(bounce==0) out
    		if(c==a+2&&d==b+2&&fang(turn)&&mapp[a+1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a+2&&d==b-2&&fang(turn)&&mapp[a+1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a-2&&d==b+2&&fang(turn)&&mapp[a-1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a-2&&d==b-2&&fang(turn)&&mapp[a-1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==4+extra)
    	{
    		if(bounce==0) out
    		if(c-a==2&&d-b==1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-2&&d-b==1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-2&&d-b==-1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==2&&d-b==-1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==5+extra)
    	{
    		if(bounce==0) out
    		if(a==c)
    		{	
    			if(d>b)
    			{
    				for(register int i=b+1;i<d;i++) if(mapp[a][i]) out					//有障碍 
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}			//判断吃,更新 
    			}
    			
    			else if(d<b)
    			{
    				for(register int i=b-1;i>d;i--) if(mapp[a][i]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else out
    		}
    		
    		else if(b==d)
    		{
    			if(c>a)
    			{
    				for(register int i=a+1;i<c;i++) 
    				if(mapp[i][b]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else if(c<a)
    			{
    				for(register int i=a-1;i>c+1;i--)
    				if(mapp[i][b]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else out
    		}
    		
    		else out
    	}
    	
    	if(mapp[a][b]==6+extra)		//这里一定要仔细。。。
    	{
    		if(bounce==0) out
    		if(c-a==2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a+1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==3&&d-b==2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a-1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-3&&d-b==2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a+1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==3&&d-b==-2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a-1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-3&&d-b==-2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==7+extra)
    	{
    		if(bounce==0) out
    		if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		out
    	}
    	
    	out
    }
    

    接下来是判断将军

    • 其实我们发现,将军函数的代码和move中大部分重合

    • 其实我们发现,将军函数本可以和move结合

    • 但我就不 (原因是我这么写然后写挂了改了半个小时才改回来)

    inline void check()			// 检查将军 
    {
    	for(register int i=0;i<=9;i++)
    	{
    		for(register int j=0;j<=8;j++)		//暴力枚举每一个点
    		{
    			if(mapp[i][j]==0) continue;
    			
    			checkmate(i,j);					//有棋则搜
    			
    			if(jiang) return;				//如果搜到了也就没必要继续了
    		}
    	}
    }
    
    • 再来一个define
    #define checkok {jiang=1;return;}	//符合将军条件则标记,返回
    

    放表:

    inline void checkmate(int p,int q)
    {
    	if(mapp[p][q]>10) checkturn=1,checkextra=10;	//checkturn是这颗棋的目标,checkextra和move中的extra同理
    	else checkturn=11,checkextra=0;
    	
    	if(mapp[p][q]==1+checkextra)
    	{
    		if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok		//一定要判断边界
    		if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok		//虽然理论上不判断也可以
    		if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok		//因为边界之外的棋不会有目标编号
    		if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok		//但是我没判断就是死了,所以。。。
    	}
    	
    	if(mapp[p][q]==2+checkextra)
    	{
    		if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
    	}
    	
    	if(mapp[p][q]==3+checkextra)
    	{
    		if(mapp[p+2][q+2]==checkturn&&mapp[p+1][q+1]==0&&0<=p+2&&p+2<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p-2][q+2]==checkturn&&mapp[p-1][q+1]==0&&0<=p-2&&p-2<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+2][q-2]==checkturn&&mapp[p+1][q-1]==0&&0<=p+2&&p+2<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-2][q-2]==checkturn&&mapp[p-1][q-1]==0&&0<=p-2&&p-2<=9&&0<=q-2&&q-2<=8) checkok
    	}
    	
    	if(mapp[p][q]==4+checkextra)
    	{
    		if(mapp[p+1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p+1&&p+1<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+2][q+1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+2][q-1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p+1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p+1&&p+1<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p-1&&p-1<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-2][q-1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-2][q+1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p-1&&p-1<=9&&0<=q+2&&q+2<=8) checkok
    	}
    	
    	if(mapp[p][q]==5+checkextra)
    	{
    		for(register int i=p+1;i<=9;i++)
    		{
    			if(mapp[i][q]==checkturn) checkok
    			if(mapp[i][q]!=0) return;
    		}
    		
    		for(register int i=p-1;i>=0;i--)
    		{
    			if(mapp[i][q]==checkturn) checkok
    			if(mapp[i][q]!=0) return;
    		}
    		
    		for(register int i=q+1;i<=8;i++)
    		{
    			if(mapp[p][i]==checkturn) checkok
    			if(mapp[p][i]!=0) return;
    		}
    		
    		for(register int i=q-1;i>=0;i--)
    		{
    			if(mapp[p][i]==checkturn) checkok
    			if(mapp[p][i]!=0) return;
    		}
    	}
    	
    	if(mapp[p][q]==6+checkextra)
    	{
    		if(mapp[p+2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p+1][q+2]==0&&0<=p+2&&p+2<=9&&0<=q+3&&q+3<=8) checkok
    		if(mapp[p+3][q+2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q+1]==0&&0<=p+3&&p+3<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+3][q-2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q-1]==0&&0<=p+3&&p+3<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p+2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p+1][q-2]==0&&0<=p+2&&p+2<=9&&0<=q-3&&q-3<=8) checkok
    		if(mapp[p-2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p-1][q-2]==0&&0<=p-2&&p-2<=9&&0<=q-3&&q-3<=8) checkok
    		if(mapp[p-3][q-2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q-1]==0&&0<=p-3&&p-3<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-3][q+2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q+1]==0&&0<=p-3&&p-3<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p-2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p-1][q+2]==0&&0<=p-2&&p-2<=9&&0<=q+3&&q+3<=8) checkok
    	}
    	
    	if(mapp[p][q]==7+checkextra)
    	{
    		if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
    	}
    }
    

    最后我们来输出

    inline void print()			//输出 
    {
    	if(mapp[c][d]==1) printf("red captain;");		//直接判终点的那颗棋
    	else if(mapp[c][d]==2) printf("red guard;");		//因为在起点的那颗被移过来了
    	else if(mapp[c][d]==3) printf("red elephant;");
    	else if(mapp[c][d]==4) printf("red horse;");
    	else if(mapp[c][d]==5) printf("red car;");
    	else if(mapp[c][d]==6) printf("red duck;");
    	else if(mapp[c][d]==7) printf("red soldier;");
    	else if(mapp[c][d]==11) printf("blue captain;");
    	else if(mapp[c][d]==12) printf("blue guard;");
    	else if(mapp[c][d]==13) printf("blue elephant;");
    	else if(mapp[c][d]==14) printf("blue horse;");
    	else if(mapp[c][d]==15) printf("blue car;");
    	else if(mapp[c][d]==16) printf("blue duck;");
    	else if(mapp[c][d]==17) printf("blue soldier;");
    	
    	if(gai==1) printf("red captain;");		//gai记录被修改的
    	else if(gai==2) printf("red guard;");
    	else if(gai==3) printf("red elephant;");
    	else if(gai==4) printf("red horse;");
    	else if(gai==5) printf("red car;");
    	else if(gai==6) printf("red duck;");
    	else if(gai==7) printf("red soldier;");
    	else if(gai==11) printf("blue captain;");
    	else if(gai==12) printf("blue guard;");
    	else if(gai==13) printf("blue elephant;");
    	else if(gai==14) printf("blue horse;");
    	else if(gai==15) printf("blue car;");
    	else if(gai==16) printf("blue duck;");
    	else if(gai==17) printf("blue soldier;");
    	else printf("NA;");						//注意没有的话输出NA
    	
    	if(capture==0&&jiang) printf("yes;");
    	else printf("no;");
    	
    	if(capture) puts("yes");				//注意这里输出没有分号!!!
    	else puts("no");
    }
    

    于是我们愉快的A掉了这道题

    放代码(我提交的时候的代码,内含我写这道题时自己放的注释):

    //记得每次移动前加 lose(c,d) 
    //注意转换turn 
    //注意移动时清空之前的格子 
    //复制粘贴时记得进行必要修改 
    //注意棋盘的边界 
    
    //check时修改extra
    //发现其实extra是turn的10倍,但是懒得改了
    //记得captain被抓了也要标记修改了哪颗棋 
    //记得动车的时候fang()
    
    #include <bits/stdc++.h>
    //#include <windows.h>																//////////////
    using namespace std;
    #define out {flagout=1;puts("Invalid command");return;}
    #define bounce (a>=0&&a<=9&&b>=0&&b<=8&&c>=0&&c<=9&&d>=0&&d<=8)
    #define checkok {jiang=1;return;}													//////////
    
    
    int Q;
    int a,b,c,d;
    																							// 全局变量区
    																							
    																							
    int mapp[12][12];						//列 行 : 如 mapp[4][3]表红方第二个兵 
    bool turn=0;		// 红0 蓝1		//王1 士2 象3 马4 车5 鸭6 兵7  红单位,蓝双位
    
    int checkturn;		//记录check的时候对方的王 
    int hong=16,lan=16,gai;		//总兵数  被吃兵 
    																							// 红蓝变量区
    																							
    																							
    bool flagout;	//判断是否被out掉 
    bool capture=0,jiang=0;	// 1为被抓/将军
    int extra,checkextra;		// move的时候结果是什么兵的修改
    int which;		// move的时候调用的什么兵 
    																							//特殊辅助区 
    										
    //int yhong=1,ylan=2,ybai=3;													
    //void Color(int a){
    //    if(a==1) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_RED);
    //    if(a==2) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_BLUE|FOREGROUND_GREEN);
    //    if(a==3) SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_INTENSITY|FOREGROUND_GREEN|FOREGROUND_BLUE|FOREGROUND_RED);
    //}
    
    
    inline void init()			//初始化棋盘 
    {
    	mapp[0][4]=1,mapp[9][4]=11;
    	mapp[0][3]=2,mapp[0][5]=2,mapp[9][3]=12,mapp[9][5]=12;
    	mapp[0][2]=3,mapp[0][6]=3,mapp[9][2]=13,mapp[9][6]=13;
    	mapp[0][1]=4,mapp[0][7]=4,mapp[9][1]=14,mapp[9][7]=14;
    	mapp[0][0]=5,mapp[0][8]=5,mapp[9][0]=15,mapp[9][8]=15;
    	mapp[2][0]=6,mapp[2][8]=6,mapp[7][0]=16,mapp[7][8]=16;
    	mapp[3][0]=7,mapp[3][2]=7,mapp[3][4]=7,mapp[3][6]=7,mapp[3][8]=7;
    	mapp[6][0]=17,mapp[6][2]=17,mapp[6][4]=17,mapp[6][6]=17,mapp[6][8]=17;
    }
    
    void lose(int c,int d)		//判断吞兵 
    {
    	if(mapp[c][d]==1) capture=1,gai=1;
    	else if(mapp[c][d]==11) capture=2,gai=11;
    	else if(mapp[c][d]>10) gai=mapp[c][d],lan--;
    	else if(mapp[c][d]>0) gai=mapp[c][d],hong--;
    }
    
    bool fang(bool turn)		// 是哪一方在动 & bounce
    {
    	if(turn==0) return (mapp[c][d]==0||mapp[c][d]>10);
    	else return (mapp[c][d]==0||mapp[c][d]<10);
    }
    
    void exchange(int e,int extra)
    {
    	mapp[a][b]=0,mapp[c][d]=e+extra;
    	which=e+extra;
    }
    
    inline void move()
    {
    	//条件 :符合该棋的移动 路上||终点无棋 终点敌方? 没越界
    	
    	if(turn==1) extra=10;
    	
    	if(mapp[a][b]==1+extra)
    	{
    		if(bounce==0) out
    		if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(1,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==2+extra)
    	{
    		if(bounce==0) out
    		if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(2,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==3+extra)
    	{
    		if(bounce==0) out
    		if(c==a+2&&d==b+2&&fang(turn)&&mapp[a+1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a+2&&d==b-2&&fang(turn)&&mapp[a+1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a-2&&d==b+2&&fang(turn)&&mapp[a-1][b+1]==0) {lose(c,d);exchange(3,extra);return;}
    		if(c==a-2&&d==b-2&&fang(turn)&&mapp[a-1][b-1]==0) {lose(c,d);exchange(3,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==4+extra)
    	{
    		if(bounce==0) out
    		if(c-a==2&&d-b==1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-1&&d-b==2&&fang(turn)&&mapp[a][b+1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-2&&d-b==1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-2&&d-b==-1&&fang(turn)&&mapp[a-1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==-1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==1&&d-b==-2&&fang(turn)&&mapp[a][b-1]==0) {lose(c,d);exchange(4,extra);return;}
    		if(c-a==2&&d-b==-1&&fang(turn)&&mapp[a+1][b]==0) {lose(c,d);exchange(4,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==5+extra)
    	{
    		if(bounce==0) out
    		if(a==c)
    		{	
    			if(d>b)
    			{
    				for(register int i=b+1;i<d;i++) if(mapp[a][i]) out					//有障碍 
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}			//判断吃,更新 
    			}
    			
    			else if(d<b)
    			{
    				for(register int i=b-1;i>d;i--) if(mapp[a][i]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else out
    		}
    		
    		else if(b==d)
    		{
    			if(c>a)
    			{
    				for(register int i=a+1;i<c;i++) 
    				if(mapp[i][b]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else if(c<a)
    			{
    				for(register int i=a-1;i>c+1;i--)
    				if(mapp[i][b]) out
    				if(fang(turn)) {lose(c,d);exchange(5,extra);return;}
    			}
    			
    			else out
    		}
    		
    		else out
    	}
    	
    	if(mapp[a][b]==6+extra)
    	{
    		if(bounce==0) out
    		if(c-a==2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a+1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==3&&d-b==2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-2&&d-b==3&&fang(turn)&&mapp[a][b+1]==0&&mapp[a-1][b+2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-3&&d-b==2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b+1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a+1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==3&&d-b==-2&&fang(turn)&&mapp[a+1][b]==0&&mapp[a+2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-2&&d-b==-3&&fang(turn)&&mapp[a][b-1]==0&&mapp[a-1][b-2]==0) {lose(c,d);exchange(6,extra);return;}
    		if(c-a==-3&&d-b==-2&&fang(turn)&&mapp[a-1][b]==0&&mapp[a-2][b-1]==0) {lose(c,d);exchange(6,extra);return;}
    		out
    	}
    	
    	if(mapp[a][b]==7+extra)
    	{
    		if(bounce==0) out
    		if(c-a==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&b==d&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a==c&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a==c&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(c-a==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&b-d==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(c-a==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		if(a-c==1&&d-b==1&&fang(turn)) {lose(c,d);exchange(7,extra);return;}
    		out
    	}
    	
    	out
    }
    
    inline void initmove()		// 初始化 move() 
    {
    	gai=0;
    	flagout=0;
    	extra=0;
    	capture=0;
    	jiang=0;
    }
    
    inline void checkmate(int p,int q)
    {
    	if(mapp[p][q]>10) checkturn=1,checkextra=10;
    	else checkturn=11,checkextra=0;
    	
    	if(mapp[p][q]==1+checkextra)
    	{
    		if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
    	}
    	
    	if(mapp[p][q]==2+checkextra)
    	{
    		if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
    	}
    	
    	if(mapp[p][q]==3+checkextra)
    	{
    		if(mapp[p+2][q+2]==checkturn&&mapp[p+1][q+1]==0&&0<=p+2&&p+2<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p-2][q+2]==checkturn&&mapp[p-1][q+1]==0&&0<=p-2&&p-2<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+2][q-2]==checkturn&&mapp[p+1][q-1]==0&&0<=p+2&&p+2<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-2][q-2]==checkturn&&mapp[p-1][q-1]==0&&0<=p-2&&p-2<=9&&0<=q-2&&q-2<=8) checkok
    	}
    	
    	if(mapp[p][q]==4+checkextra)
    	{
    		if(mapp[p+1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p+1&&p+1<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+2][q+1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+2][q-1]==checkturn&&mapp[p+1][q]==0&&0<=p+2&&p+2<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p+1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p+1&&p+1<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-1][q-2]==checkturn&&mapp[p][q-1]==0&&0<=p-1&&p-1<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-2][q-1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-2][q+1]==checkturn&&mapp[p-1][q]==0&&0<=p-2&&p-2<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+2]==checkturn&&mapp[p][q+1]==0&&0<=p-1&&p-1<=9&&0<=q+2&&q+2<=8) checkok
    	}
    	
    	if(mapp[p][q]==5+checkextra)
    	{
    		for(register int i=p+1;i<=9;i++)
    		{
    			if(mapp[i][q]==checkturn) checkok
    			if(mapp[i][q]!=0) return;
    		}
    		
    		for(register int i=p-1;i>=0;i--)
    		{
    			if(mapp[i][q]==checkturn) checkok
    			if(mapp[i][q]!=0) return;
    		}
    		
    		for(register int i=q+1;i<=8;i++)
    		{
    			if(mapp[p][i]==checkturn) checkok
    			if(mapp[p][i]!=0) return;
    		}
    		
    		for(register int i=q-1;i>=0;i--)
    		{
    			if(mapp[p][i]==checkturn) checkok
    			if(mapp[p][i]!=0) return;
    		}
    	}
    	
    	if(mapp[p][q]==6+checkextra)
    	{
    		if(mapp[p+2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p+1][q+2]==0&&0<=p+2&&p+2<=9&&0<=q+3&&q+3<=8) checkok
    		if(mapp[p+3][q+2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q+1]==0&&0<=p+3&&p+3<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p+3][q-2]==checkturn&&mapp[p+1][q]==0&&mapp[p+2][q-1]==0&&0<=p+3&&p+3<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p+2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p+1][q-2]==0&&0<=p+2&&p+2<=9&&0<=q-3&&q-3<=8) checkok
    		if(mapp[p-2][q-3]==checkturn&&mapp[p][q-1]==0&&mapp[p-1][q-2]==0&&0<=p-2&&p-2<=9&&0<=q-3&&q-3<=8) checkok
    		if(mapp[p-3][q-2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q-1]==0&&0<=p-3&&p-3<=9&&0<=q-2&&q-2<=8) checkok
    		if(mapp[p-3][q+2]==checkturn&&mapp[p-1][q]==0&&mapp[p-2][q+1]==0&&0<=p-3&&p-3<=9&&0<=q+2&&q+2<=8) checkok
    		if(mapp[p-2][q+3]==checkturn&&mapp[p][q+1]==0&&mapp[p-1][q+2]==0&&0<=p-2&&p-2<=9&&0<=q+3&&q+3<=8) checkok
    	}
    	
    	if(mapp[p][q]==7+checkextra)
    	{
    		if(mapp[p+1][q]==checkturn&&0<=p+1&&p+1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p-1][q]==checkturn&&0<=p-1&&p-1<=9&&0<=q&&q<=8) checkok
    		if(mapp[p][q+1]==checkturn&&0<=p&&p<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p][q-1]==checkturn&&0<=p&&p<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p+1][q+1]==checkturn&&0<=p+1&&p+1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p-1][q+1]==checkturn&&0<=p-1&&p-1<=9&&0<=q+1&&q+1<=8) checkok
    		if(mapp[p+1][q-1]==checkturn&&0<=p+1&&p+1<=9&&0<=q-1&&q-1<=8) checkok
    		if(mapp[p-1][q-1]==checkturn&&0<=p-1&&p-1<=9&&0<=q-1&&q-1<=8) checkok
    	}
    }
    
    inline void check()			// 检查将军 
    {
    	for(register int i=0;i<=9;i++)
    	{
    		for(register int j=0;j<=8;j++)
    		{
    			if(mapp[i][j]==0) continue;
    			
    			checkmate(i,j);
    			
    			if(jiang) return;
    		}
    	}
    }
    
    inline void print()			//输出 
    {
    	if(mapp[c][d]==1) printf("red captain;");
    	else if(mapp[c][d]==2) printf("red guard;");
    	else if(mapp[c][d]==3) printf("red elephant;");
    	else if(mapp[c][d]==4) printf("red horse;");
    	else if(mapp[c][d]==5) printf("red car;");
    	else if(mapp[c][d]==6) printf("red duck;");
    	else if(mapp[c][d]==7) printf("red soldier;");
    	else if(mapp[c][d]==11) printf("blue captain;");
    	else if(mapp[c][d]==12) printf("blue guard;");
    	else if(mapp[c][d]==13) printf("blue elephant;");
    	else if(mapp[c][d]==14) printf("blue horse;");
    	else if(mapp[c][d]==15) printf("blue car;");
    	else if(mapp[c][d]==16) printf("blue duck;");
    	else if(mapp[c][d]==17) printf("blue soldier;");
    	
    	if(gai==1) printf("red captain;");
    	else if(gai==2) printf("red guard;");
    	else if(gai==3) printf("red elephant;");
    	else if(gai==4) printf("red horse;");
    	else if(gai==5) printf("red car;");
    	else if(gai==6) printf("red duck;");
    	else if(gai==7) printf("red soldier;");
    	else if(gai==11) printf("blue captain;");
    	else if(gai==12) printf("blue guard;");
    	else if(gai==13) printf("blue elephant;");
    	else if(gai==14) printf("blue horse;");
    	else if(gai==15) printf("blue car;");
    	else if(gai==16) printf("blue duck;");
    	else if(gai==17) printf("blue soldier;");
    	else printf("NA;");
    	
    	if(capture==0&&jiang) printf("yes;");
    	else printf("no;");
    	
    	if(capture) puts("yes");
    	else puts("no");
    }
    
    int main()
    {
    //	freopen("2test.in","r",stdin);
    //	freopen("test.out","w",stdout);
    	
    	init();
    //	Color(ybai);					/////
    //	int cc=0;
    	
    //	for(register int i=9;i>=0;i--)
    //	{
    //		for(register int j=8;j>=0;j--)
    //		{
    //			cout<<setw(5)<<mapp[i][j];
    //		}
    //		puts("");
    //	}
    	
    	scanf("%d",&Q);
    	
    	for(register int i=1;i<=Q;i++)
    	{
    //		cout<<i<<" ";					////
    		
    		scanf("%d%d%d%d",&a,&b,&c,&d);
    		
    		if(capture) {puts("Invalid command");continue;}
    		
    		initmove();
    		move();
    	
    		if(flagout) continue;
    		
    //		if(i<=586) 
    //		system("cls");								/////
    //		for(register int i=9;i>=0;i--)
    //		{
    //			for(register int j=0;j<=8;j++)
    //			{
    //				if(mapp[i][j]<10&&mapp[i][j]!=0)
    //				{
    //					Color(yhong),cout<<setw(5)<<mapp[i][j],Color(ybai);
    //				}
    //				else if(mapp[i][j]>10)
    //				{
    //					Color(ylan),cout<<setw(5)<<mapp[i][j],Color(ybai);
    //				}
    //				else Color(ybai),cout<<setw(5)<<mapp[i][j];
    //			}
    //			puts("");
    //		}
    //		puts(""),puts("");											/////
    		
    		check();
    		
    		print();
    		
    		if(turn==0) turn=1;
    		else turn=0;
    		
    //		if(i>=590) system("pause");
    //		if(i>=357) 
    	}
    	
    	return 0;
    }
    

    写题解不易,兹磁一下呗! By Possible \color{white}\texttt{By Possible}

    • 1

    信息

    ID
    4366
    时间
    1000ms
    内存
    500MiB
    难度
    5
    标签
    递交数
    0
    已通过
    0
    上传者