题目
UVa1589
题解
这是我做的第一题非水题,可以明显感觉到水题与非水题之间的差别...
题目是以象棋为背景的,问题就是比较典型(?)的棋盘上的问题。
拿到题第一步是处理输入,照常做就好,毕竟做水题的时候对各种状况都有了尝试。不过需要注意的一点是,这里读入棋子 'C', 'R' 等时如果采用 getchar + %c 很可能过不了(即使测试的时候能过),笔者就是在这里n多次WA了,最后换成 %s 才终于AC。
接下来是对数据的处理。
我一开始想到的也是把红棋所能到的地方都作标记来处理。不过后来想这好像有点麻烦,因为这种做法应该(我没具体尝试)只能在把全部红棋读入后,再遍历一次才能开始判断。而且遍历的过程貌似也不算简单,起码代码量繁多。再之这样做就会需要结构体的辅助,按顺序紫书只是到函数了而已。
所以我想了另一种方法:每次数据读入都立刻把棋子储存到棋盘里,在全部都读完了再开始对黑将的可走路径进行是否被击杀的判断。最终我对比其他作者的代码,代码量都是要少了不小的(一般都用了一百起步甚至两百行代码,笔者只有90行不到)。
在判断的时候由于同一条轴(比如x轴)是要分两个方向(正方)遍历的。这里就有一个小技巧,写第一层的for用于操控方向(-1或者1),然后第二层则只需令j += i即可按方向遍历整个轴,同时代码量减少,不必写过多重复的代码(这会令我烦躁)。
代码
#include <stdio.h>
#include <string.h>
char Map[12][11];
void solve(int x, int y);
int G(int x, int y); //判断会不会被红帅击杀
int H(int x, int y); //判断会不会被红马击杀
int RL(int x, int y); //判断会不会被红炮、车、帅击杀
int main() {
#ifdef TEST
freopen("test.in", "r", stdin);
freopen("test.out", "w", stdout);
#endif
int n, bx, by, rx, ry; char ch[3];
while (scanf("%d%d%d", &n, &bx, &by) && by) {
for (int i = 0; i < 11; i++) memset(Map[i], '0', sizeof(Map[i]));
for (int i = 0; i < n; i++)
scanf("%s%d%d", ch, &rx, &ry), Map[rx][ry] = ch[0];
solve(bx, by);
}
return 0;
}
void solve(int x, int y) {
int flag = 1;
//直接飞将获得胜利
if (G(x, y)) { printf("NO\n"); return; }
//i控制方向,判断黑将四个方位中可走的路径是否被击杀
for (int i = -1; i <= 1; i += 2) {
if (x + i >= 1 && x + i <= 3){
if (!RL(x + i, y) && !H(x + i, y))
flag = 0;
}
if (y + i <= 6 && y + i >= 4) {
if (!RL(x, y + i) && !H(x, y + i))
flag = 0;
}
}
if (flag) printf("YES\n");
else printf("NO\n");
}
int RL(int x, int y) {
int flag = 0;
//i控制方向,j遍历,考虑路上所有情况共5种
for (int i = -1; i <= 1; i += 2, flag = 0) for (int j = x + i; j <= 10 && j >= 1; j += i) {
if (Map[j][y] == '0') continue;
else if (flag) {
if (Map[j][y] == 'C') return 1;
else break;
}
else if (Map[j][y] == 'H' || Map[j][y] == 'C') flag = 1;
else return 1;
}
for (int i = -1; i <= 1; i += 2, flag = 0) for (int j = y + i; j <= 9 && j >= 1; j += i) {
if (Map[x][j] == '0') continue;
else if (flag) {
if (Map[x][j] == 'C') return 1;
else break;
}
else if (Map[x][j] == 'H' || Map[x][j] == 'C') flag = 1;
else return 1;
}
return 0;
}
int H(int x, int y) {
for (int i = -1; i <= 1; i += 2) for (int j = -1; j <= 1; j += 2)
if (x + i && Map[x + i][y + j] == '0') {
if (Map[x + i][y + 2 * j] == 'H')
return 1;
else if (x + 2 * i && Map[x + 2 * i][y + j] == 'H')
return 1;
}
return 0;
}
int G(int x, int y){
for (int i = x + 1; i <= 10; i++)
if (Map[i][y] == '0') continue;
else if (Map[i][y] == 'G') return 1;
else return 0;
return 0;
}