原题链接:https://vjudge.net/problem/UVA-1589
分类:函数
备注:复杂模拟
注意
- 各个棋子和将的相对位置是怎么样的。
- 不管是什么棋子都要考虑是否有其它棋子拦路。
- 将能飞将军吃掉帅,将也有可能吃其它棋子。
代码如下:
#include<stdio.h>
const int maxn = 20;
const int dr[] = { -1,1,0,0 };//将走步
const int dc[] = { 0,0,-1,1 };
const int hr[] = { -2,-2,1,-1,2,2,1,-1 };//马走步
const int hc[] = { 1,-1,-2,-2,-1,1,2,2 };
int N, row, col, over[3];//收录被吃掉的红子
struct piece
{
char ch;
int x, y;
}p[maxn];
char read()
{
char ch = getchar();
while (ch == ' ' || ch == '\n')ch = getchar();
return ch;
}
int check_G(int a, int b, int pos)//帅 1 - 将军,0 = 失败
{
if (b != p[pos].y)return 0;
for (int i = 0; i < N; i++)
if (p[i].y == p[pos].y && p[i].x<p[pos].x && p[i].x>a)return 0;
return 1;
}
int check_R(int a, int b, int pos)//车
{
if (a == p[pos].x)
{
if (b > p[pos].y)//车在将的正左
{
for (int i = 0; i < N; i++)
if (p[i].x == a && p[i].y > p[pos].y&& p[i].y < b)
return 0;
}
else //车在将的正右
{
for (int i = 0; i < N; i++)
if (p[i].x == a && p[i].y<p[pos].y && p[i].y>b)
return 0;
}
return 1;
}
else if (b == p[pos].y)
{
if (a > p[pos].x)//车在将的正上
{
for (int i = 0; i < N; i++)
if (p[i].y == b && p[i].x > p[pos].x&& p[i].x < a)
return 0;
}
else//车在将的正下
{
for (int i = 0; i < N; i++)
if (p[i].y == b && p[i].x < p[pos].x && p[i].x > a)
return 0;
}
return 1;
}
return 0;
}
int check_H(int a, int b, int pos)//马
{
for (int i = 0; i < 8; i++)//判断吃将
{
int row2 = p[pos].x + hr[i], col2 = p[pos].y + hc[i];
if (row2 == a && col2 == b)
{
int tx, ty;//蹩脚判断
if (i == 0 || i == 1)tx = p[pos].x - 1, ty = p[pos].y;
if (i == 2 || i == 3)tx = p[pos].x, ty = p[pos].y - 1;
if (i == 4 || i == 5)tx = p[pos].x + 1, ty = p[pos].y;
if (i == 6 || i == 7)tx = p[pos].x, ty = p[pos].y + 1;
for (int i = 0; i < N; i++)if (i != pos && p[i].x == tx && p[i].y == ty)return 0;
return 1;
}
}
return 0;
}
int check_C(int a, int b, int pos)//炮
{
int cnt = 0;
if (a == p[pos].x)
{
if (b > p[pos].y)//炮在将的正左
{
for (int i = 0; i < N; i++)
if (p[i].x == a && p[i].y > p[pos].y&& p[i].y < b)
cnt++;
}
else //炮在将的正右
{
for (int i = 0; i < N; i++)
if (p[i].x == a && p[i].y < p[pos].y && p[i].y > b)
cnt++;
}
}
else if (b == p[pos].y)
{
if (a < p[pos].x)//炮在将的正下
{
for (int i = 0; i < N; i++)
if (p[i].y == b && p[i].x < p[pos].x && p[i].x > a)
cnt++;
}
else if (a > p[pos].x)//炮在将的正上
{
for (int i = 0; i < N; i++)
if (p[i].y == b && p[i].x > p[pos].x&& p[i].x < a)
cnt++;
}
}
if (cnt == 1)return 1;
return 0;
}
int simulate(int a, int b)
{
for (int i = 0; i < N; i++)
{
if (p[i].ch == 'G' && check_G(a, b, i))return 1;
if (p[i].ch == 'R' && check_R(a, b, i))return 1;
if (p[i].ch == 'H' && check_H(a, b, i))return 1;
if (p[i].ch == 'C' && check_C(a, b, i))return 1;
}
return 0;
}
int main(void)
{
while (scanf("%d%d%d", &N, &row, &col) == 3 && N)
{
over[0] = 15; int judge = 0;//重置
for (int i = 0; i < N; i++) { p[i].ch = read(); scanf("%d%d", &p[i].x, &p[i].y); }
for (int i = 0; i < N; i++)//判断红方是否被飞将军
if (p[i].ch == 'G' && p[i].y == col)
{
judge = 1;
for (int j = 0; j < N; j++)
if (p[j].y == col && p[j].x > row&& p[j].x < p[i].x) { judge = 0; break; }
break;
}
if (judge) { printf("NO\n"); continue; }
for (int i = 0; i < 4; i++)
{
int row2 = row + dr[i], col2 = col + dc[i];
p[over[0]].x = over[1], p[over[0]].y = over[2];//回溯被吃掉的子
if (row2 >= 1 && row2 <= 3 && col2 >= 4 && col2 <= 6)//将的合理移动
{
for (int i = 0; i < N; i++)//红方可能被吃掉子
if (row2 == p[i].x && col2 == p[i].y)
{
over[0] = i; over[1] = row2; over[2] = col2;
p[i].x = p[i].y = 0;
}
if (!simulate(row2, col2))judge = 1;//一旦有不能将军的情况,NO
}
}
if (judge)printf("NO\n"); else printf("YES\n");
}
return 0;
}