模拟是否将死的局面。
马 : 向各个方向先走两步,再往垂直与这个方向上走一步,若这个方向的第一个位置有棋子,则这个方向上不能走。
炮: 直线方向上的第一个棋子和第二个棋子之间的位置都可以吃。
车: 上下左右
将/帅: 不能见面,若是见面,使它们见面的那一方输,所以开始时要特判一下,如果此时将帅见面了,则是黑方输,输出NO
这里特别注意的是,将是可以吃棋子的,也即是可以有将先吃了一颗红方的棋,然后另外的棋子可以走到这里。也就是说标记时要考虑到有棋子的位置能否走。
上面考虑清楚了,基本代码就出来了。
毕竟将能走的位置也是有限的,顶多4个,考虑这几个位置上是不是都有红方的棋子能走到。
这道题wa了很多次…..本来是前天写的题,今天趁头脑还比较清醒的时候拿出来写一写,果然理一理思路一发过了…..
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 15
int n,ja,jb;
int ori[maxn][maxn];
int vis[maxn][maxn];
int bcan[4][10];
int way[4][2] = {-1,0,1,0,0,-1,0,1};
struct qz
{
int k;
int i,j;
qz(int a,int b,int c)
{
k = a; i = b; j = c;
}
qz(){}
}q[maxn];
int ra,rb;
int check(int i,int j)
{
if(i > 10 || i < 1 || j > 9 || j < 1) return 0;
else return 1;
}
int lf(int w,int i,int j,int k) //四个方向上找到一个棋子,k是看标不标记找的路上的
{
int ci = i,cj = j;
while(1)
{
ci = ci+way[w][0] , cj = cj + way[w][1];
if(check(ci,cj) == 0) return -1; //找到边界了
if(k == 1) vis[ci][cj] = 1;
if(ori[ci][cj] == 1)
{
if(w <= 1) return ci;
else return cj;
}
}
}
int msize = 0;
int solve()
{
//cout<<"n "<<n<<endl;
for(int i = 0; i < n ;i ++)
{
if(q[i].k == 1)
continue;
else if(q[i].k == 2) //horse 考虑憋马腿的情况。
{
for(int j = 0; j < 4 ; j++)
{
int ci = q[i].i+way[j][0],cj = q[i].j + way[j][1];
if(check(ci,cj))
if(ori[ci][cj] == 1) continue;
int i1,j1,i2,j2;
int mi = q[i].i+way[j][0]*2, mj = q[i].j + way[j][1]*2;
if(j <= 1)
{
i2 = i1 = mi; j1 = mj + 1; j2 = mj-1;
}
else
{
j2 = j1 = mj; i1 = mi+1; i2 = mi-1;
}
if(check(i1,j1)) vis[i1][j1] = 1;
if(check(i2,j2)) vis[i2][j2] = 1;
}
}
else if(q[i].k == 3)
{
for(int j = 0; j < 4; j++)
{
int one = lf(j,q[i].i,q[i].j,0);
if(one != -1) //找到炮台
{
if(j <= 1)
lf(j,one,q[i].j,1); //标记第一个后面的所有位置
else
lf(j,q[i].i,one,1);
}
}
}
else
{
for(int j = 0; j < 4 ; j++)
lf(j,q[i].i,q[i].j,1);
}
}
for(int i = 0; i < msize; i++)
{
if(vis[bcan[i][0]][bcan[i][1]] == 0)
return 0;
}
return 1;
}
int main()
{
char s[2];
while(~scanf("%d%d%d",&n,&ja,&jb) &&n+ja+jb)
{
int a,b;
msize = 0;
memset(vis,0,sizeof(vis));
memset(ori,0,sizeof(ori));
memset(bcan,0,sizeof(bcan));
for(int i = 0; i < n ; i++)
{
cin>>s>>a>>b;
int kind = -1;
if(s[0] == 'G')
ra = a,rb = b, kind = 1;
else if(s[0] == 'H') kind = 2;
else if(s[0] == 'C') kind = 3;
else kind = 4;
ori[a][b] = 1;
q[i] = qz(kind,a,b);
}
for(int i = 0; i < 4 ; i++) //红方的帅能否直接吃掉将,将这个位置标记
{
int bi = ja+way[i][0],bj = jb+way[i][1];
if(bi <= 3 && bi >= 1 && bj >= 4 && bj <= 6)
bcan[msize][0] = bi,bcan[msize++][1] = bj;
if(rb == bj)
{
int flag = 0;
for(int j = ra-1; j > bi; j--)
if(ori[j][bj] == 1)
{ flag = 1;}
if(flag == 0)
vis[bi][bj] = 1;
}
}
if(rb == jb) //初始 将能否直接吃掉帅
{
int flag = 0;
for(int i = ra-1; i > ja; i--)
if(ori[i][jb] == 1) flag = 1;
if(flag == 0) {printf("NO\n");continue;}
}
if(solve())
printf("YES\n");
else printf("NO\n");
}
}