徐州矿大冬令营第一天训练题,写的简直要吐血,一开始写了半下午,晚上看了题解找bug找了两个多小时…最后竟然多写了一个=…啊啊啊啊啊啊!!!
[题解]: 首先,判断黑方的将是不是可以直接以“飞将”的方式将死红方。如果黑方不能直接将 死红方,则对黑方的将下一步可以走到的交叉点,分析在这个交叉点是否会被红方吃掉:先 判断这个交叉点的四个方向上有没有红方的車;如果不存在車的威胁,则继续判断是否存在 红方的炮的威胁;如果不存在炮的威胁,则继续判断是否存在红方的马的威胁,当然还要考 虑马是否存在“蹩马腿”的状况。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,x1,y1;
char mp[22][22];
int dir[4][2]={1,0,-1,0,0,1,0,-1}; // 上下左右四个方向
int fx[8][2]={1,2,1,-2,2,1,2,-1,-1,2,-1,-2,-2,1,-2,1}; // 马的位置
int bx[8][2]={1,1,1,-1,1,1,1,-1,-1,1,-1,-1,-1,1,-1,-1}; ; // 绊马蹄位置
bool check1(int x,int y){ // 红方和黑方的将面对面
for(int i=x+1;i<=10;i++){
if(mp[i][y]=='\0')continue;
if(mp[i][y]!='G')return false;
return true;
}
return false;
}
bool check(int x,int y){ // 判断黑方的将是否能被将死
if(check1(x,y))return false;
for(int i=0;i<4;i++){
int h=x+dir[i][0];
int l=y+dir[i][1];
while(h>=1&&h<=10&&l>=1&&l<=9){
if(mp[h][l]=='\0'){
h+=dir[i][0];
l+=dir[i][1];
continue;
}
if(mp[h][l]=='R')return false; // 判車
int hh=h+dir[i][0];
int ll=l+dir[i][1];
while(hh>=1&&hh<=10&&ll>=1&&ll<=9){
if(mp[hh][ll]=='\0'){
hh+=dir[i][0];
ll+=dir[i][1];
continue;
}
if(mp[hh][ll]=='C')return false; // 判炮
break;
}
break;
}
}
for(int i=0;i<8;i++){ // 判马
int h=x+fx[i][0],l=y+fx[i][1];
int hh=x+bx[i][0],ll=y+bx[i][1];
if(h>=1&&h<=10&&l>=1&&l<=9&&mp[h][l]=='H'&&mp[hh][ll]=='\0')
return false;
}
return true;
}
int main()
{
while(~scanf("%d%d%d",&n,&x1,&y1)&&(n+x1+y1)){
memset(mp,0,sizeof(mp));
char ch[5];
int a,b;
for(int i=1;i<=n;i++){
scanf("%s%d%d",ch,&a,&b);
mp[a][b]=ch[0];
}
if(check1(x1,y1)){ // 黑方飞将获胜(黑方不能被将死)
printf("NO\n");
continue;
}
bool flag=true;
for(int i=0;i<4;i++){ //枚举黑方的将走的四个位置
int x=x1+dir[i][0];
int y=y1+dir[i][1];
// cout<<x1<<' '<<y1<<endl;
if(x>=1&&x<=3&&y>=4&&y<=6){
char cc=mp[x][y];
mp[x][y]='\0';
if(check(x,y)){
flag=false;
// cout<<x<<' '<<y<<endl;
printf("NO\n");
break;
}
mp[x][y]=cc;
}
}
if(flag)printf("YES\n");
}
return 0;
}