文章目录
UVA1589 象棋 Xiangqi
问题
代码
#include <assert.h>
#include <iostream>
#include <vector>
#include <cstring>
#define _for(i, a, b) for(int i = (a); i < (b); ++i)
using namespace std;
struct Point
{
int x, y;
Point(int x = 0, int y = 0) : x(x), y(y) {}
};
typedef Point Vector;
Vector operator + (const Vector &A, const Vector &B) {return Vector(A.x + B.x, A.y + B.y);}
Vector operator - (const Vector &A, const Vector &B) {return Vector(A.x - B.x, A.y - B.y);}
Vector operator * (const Vector &A, int p) {return Vector(A.x * p, A.y * p);}
Vector operator / (const Vector &A, int p) {return Vector(A.x / p, A.y / p);}
bool operator == (const Vector &A, const Vector &B) {return A.x == B.x && A.y == B.y;}
bool operator < (const Vector &A, const Vector &B) {return A.x < B.x || A.x == B.x && A.y < B.y;}
istream & operator >> (istream &is, Vector &A) {return is >> A.x >> A.y;}
ostream & operator << (ostream &os, const Vector &A) {return os << A.x << " " << A.y;}
bool inRange(int x, int leftOrUp, int rightOrDown)
{
if(leftOrUp > rightOrDown) return inRange(x, rightOrDown, leftOrUp);
return leftOrUp <= x && x <= rightOrDown;
}
Vector blackG, redG; // 将帅
char board[16][16];
vector<Vector> DIRS = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; // 四个方向
vector<Vector> HDIRS = {{-2, -1}, {-2, 1}, {-1, -2}, {1, -2}, {-1, 2}, {1, 2}, {2, -1}, {2, 1}};
vector<Vector> redPieces;
bool inBPalace(const Vector &bPos) {return inRange(bPos.x, 1, 3) && inRange(bPos.y, 4, 6);}
// p1能不能直接飞到p2,中间有sz个棋子
bool canFly(const Vector &p1, const Vector &p2, int sz = 0)
{
bool v = (p1.x == p2.x), h = (p1.y == p2.y); // 判断是否在一条线上
assert(v || h); assert(!(v && h)); // 确保在一条线上但又不重合
int highX = min(p1.x, p2.x), lowX = max(p1.x, p2.x);
int leftY = min(p1.y, p2.y), rightY = max(p1.y, p2.y);
int cnt = 0;
if(v)
{
_for(y, leftY + 1, rightY)
if(board[p1.x][y] && ++cnt > sz) return false;
return cnt == sz;
}
_for(x, highX + 1, lowX)
if(board[x][p1.y] && ++cnt > sz) return false;
return cnt == sz;
}
// mine
// mine
// r 上面的红棋子会不会吃掉b上面的黑棋子
bool checkmate(const Vector &r, const Vector &b)
{
bool ans = true;
switch(board[r.x][r.y])
{
case 'G': // general 将帅照面
return r.y == b.y && canFly(r, b);
case 'R': // chariot 车吃将
return (r.x == b.x || r.y == b.y) && canFly(r, b);
case 'H': // horse 马往各个方向尝试着跳
for(const auto &HD : HDIRS)
{
Vector hPos = r + HD, legPos = r + HD / 2;
if(hPos == b && board[legPos.x][legPos.y] == 0) return true;
}
return false;
case 'C': // 炮打
return (r.x == b.x || r.y == b.y) && canFly(r, b, 1);
default:
assert(false);
break;
}
// return false;
}
bool canWin() {
assert(inBPalace(blackG));
if(blackG.y == redG.y && canFly(blackG, redG))return false;
for(const auto &D : DIRS)
{
Point bp = blackG + D;
if(!inBPalace(bp)) continue; // 走出宫殿,不可以
char back = board[bp.x][bp.y];
board[bp.x][bp.y] = 0; // 红字可能被吃掉
bool live = true; // 黑王状态(活,死)
for(const auto &r : redPieces)
{
if(board[r.x][r.y] && checkmate(r, bp)) {
live = false;
break;
}
}
board[bp.x][bp.y] = back;
if(live) return false;
}
return true;
}
int main()
{
int N;
while(scanf("%d%d%d", &N, &(blackG.x), &(blackG.y)) == 3 && N)
// while((cin >> N >> blackG.x >> blackG.y) && N)
{
redPieces.clear();
memset(board, 0, sizeof(board));
_for(i, 0, N)
{
char type;
Point p;
// getchar();
cin >> type;
if(type == '\n') cin >> type;
scanf("%d%d", &(p.x), &(p.y));
redPieces.push_back(p);
board[p.x][p.y] = type;
if(type == 'G') redG = p;
}
puts(canWin() ? "YES" : "NO");
}
return 0;
}
总结
注意输出输入格式