One-move Checkmate (ZOJ 1598)

题目来源ZOJ 1598


搜索题,算法很简单,就是让白后在每个方向上不断搜,直到搜到某个位置能够让黑王无路可走。但实现起来很麻烦,要考虑很多边界条件。 白后不能越过白王,更蛋疼的是黑王可以不动。。。


#include<fstream>
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;

int wk[2],bk[2],wq[2];
int s[9][2]={{-1,0},{1,0},{0,1},{0,-1},{-1,-1},{1,1},{-1,1},{1,-1},{0,0}}; //八个方向,最后一个不动

int* check(){
	int *res = new int[2];
	res[0] = res[1] = 0;
	int dwq[2],dbk[2]; //逐步移动白后

	for(int i=0;i<8;i++){
		dwq[0] = wq[0]; dwq[1] = wq[1];
		while(true){
            dwq[0] += s[i][0]; dwq[1] += s[i][1];
			if((dwq[0]==wk[0]&&dwq[1]==wk[1])||(dwq[0]==bk[0]&&dwq[1]==bk[1])
			||dwq[0]<1||dwq[0]>8||dwq[1]<1||dwq[1]>8) break; //位置不合适或被白王挡住

			int j;
			for(j=0;j<9;j++){ //对黑王的每个下一个位置都检查一遍
				dbk[0] = bk[0]+s[j][0];
				dbk[1] = bk[1]+s[j][1];
				if(dbk[0]<1||dbk[0]>8||dbk[1]<1||dbk[1]>8) continue;
				int t1 = wk[0] - dbk[0], t2 = wk[1] - dbk[1];
				if(t1>=-1&&t1<=1&&t2>=-1&&t2<=1) continue;  //白王能吃掉,不用考虑
                
				int dx = dbk[0] - dwq[0], dy = dbk[1] - dwq[1];
				if(dx==0&&dy==0) break; //黑王能吃掉白后
				
				int k;
				for(k=0;k<8;k++){ //检查白后在当前位置能否攻击到该位置
					
					if(s[k][1]==0){
						if(dy!=0 || dx * s[k][0]<0) continue; //换个方向看能否攻击到
						//检查是否有白王挡着
						if(wk[1]-dwq[1]==0&&(wk[0]-dwq[0])*(wk[0]-dbk[0])<0) k=8;  //与黑王同线,但被白王挡住,则在其他方向肯定也不能攻击到黑王
						break;  

					}
					else if(s[k][0]==0){
						if(dx!=0 || dy * s[k][1]<0) continue;
						if(wk[0]-dwq[0]==0&&(wk[1]-dwq[1])*(wk[1]-dbk[1])<0) k=8; 
						break; 

					}
					else{
						if(dx*s[k][0]<=0||dy*s[k][1]<=0||dx*s[k][0]!=dy*s[k][1]) continue;
						int t1 = wk[0] - dwq[0], t2 = wk[1] - dwq[1];
						if(t1*s[k][0]>0 && t2*s[k][1]>0 && t1*s[k][0]==t2*s[k][1] && t2*(wk[1]-dbk[1])<0) k=8; 
						break;
					}
				}

				if(k==8) break; //白后在每个方向上都不能攻击到黑王
				//否则,说明白后能绝杀该位置,继续检查黑王的下一个可能位置
			}

			if(j==9){ //将白后放在该位置可行
				res[0] = dwq[0]; res[1] = dwq[1];
				return res;
			}
			//否则,继续寻找白后的下一跳
		}
	}

	return res;
}


int main(){
	freopen("input.txt","rb",stdin);
	char c1,c2,c3,c4,c5,c6;

	while(scanf("%c%c %c%c %c%c\n",&c1,&c2,&c3,&c4,&c5,&c6)==6){

		wk[0] = c1-'a'+1; wk[1] = c2-'0';
		wq[0] = c3-'a'+1; wq[1] = c4-'0';
		bk[0] = c5-'a'+1; bk[1] = c6-'0';

		int *res = check();

		if(res[0]==0) printf("no\n");
		else printf("%c%d\n",res[0]+'a'-1,res[1]);
		delete res;
	}

	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值