1 条题解
-
0
#include <cstdio> #include <cstring> #include <vector> using namespace std; struct Point { int x, y; Point(int x = 0, int y = 0) : x(x), y(y) {} }; int map[110][110]; vector<Point> jPoints; // 存储Farmer John牛的位置 vector<Point> emptyPoints; // 存储空位位置 // 检查四个点是否构成正方形 bool isSquare(Point p1, Point p2, Point p3, Point p4) { int d1 = (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y); int d2 = (p1.x-p3.x)*(p1.x-p3.x) + (p1.y-p3.y)*(p1.y-p3.y); int d3 = (p1.x-p4.x)*(p1.x-p4.x) + (p1.y-p4.y)*(p1.y-p4.y); int d4 = (p2.x-p3.x)*(p2.x-p3.x) + (p2.y-p3.y)*(p2.y-p3.y); int d5 = (p2.x-p4.x)*(p2.x-p4.x) + (p2.y-p4.y)*(p2.y-p4.y); int d6 = (p3.x-p4.x)*(p3.x-p4.x) + (p3.y-p4.y)*(p3.y-p4.y); // 正方形应有4个相等的边和2个相等的对角线 // 对角线长度是边长的√2倍,因此对角线平方是边长平方的2倍 int sides[6] = {d1, d2, d3, d4, d5, d6}; int minD = sides[0], maxD = sides[0]; for (int i = 1; i < 6; i++) { if (sides[i] < minD) minD = sides[i]; if (sides[i] > maxD) maxD = sides[i]; } // 验证是否为正方形 return maxD == 2 * minD && (d1 == minD || d1 == maxD) && (d2 == minD || d2 == maxD) && (d3 == minD || d3 == maxD) && (d4 == minD || d4 == maxD) && (d5 == minD || d5 == maxD) && (d6 == minD || d6 == maxD); } int main() { int n; scanf("%d", &n); getchar(); // 读取换行符 for (int i = 1; i <= n; i++) { for (int j = 1; j <= n; j++) { char c = getchar(); if (c == 'J') { map[i][j] = 1; jPoints.push_back(Point(i, j)); } else if (c == 'B') { map[i][j] = -1; } else { map[i][j] = 0; emptyPoints.push_back(Point(i, j)); } } getchar(); // 读取换行符 } int maxArea = 0; // 情况1:仅由现有Farmer John牛构成的正方形 int jCount = jPoints.size(); for (int i = 0; i < jCount; i++) { for (int k = i + 1; k < jCount; k++) { for (int m = k + 1; m < jCount; m++) { for (int p = m + 1; p < jCount; p++) { if (isSquare(jPoints[i], jPoints[k], jPoints[m], jPoints[p])) { int d = (jPoints[i].x-jPoints[k].x)*(jPoints[i].x-jPoints[k].x) + (jPoints[i].y-jPoints[k].y)*(jPoints[i].y-jPoints[k].y); if (d > maxArea) maxArea = d; } } } } } // 情况2:包含新放置Bessie的正方形 int emptyCount = emptyPoints.size(); for (int i = 0; i < jCount; i++) { for (int k = i + 1; k < jCount; k++) { // 计算可能的另外两个点 int x1 = jPoints[i].x + (jPoints[i].y - jPoints[k].y); int y1 = jPoints[i].y + (jPoints[k].x - jPoints[i].x); int x2 = jPoints[k].x + (jPoints[i].y - jPoints[k].y); int y2 = jPoints[k].y + (jPoints[k].x - jPoints[i].x); // 检查第一种可能的正方形 bool valid1 = (x1 >= 1 && x1 <= n && y1 >= 1 && y1 <= n) && (x2 >= 1 && x2 <= n && y2 >= 1 && y2 <= n); if (valid1) { bool hasJ1 = false, hasJ2 = false; if (map[x1][y1] == 1) hasJ1 = true; if (map[x2][y2] == 1) hasJ2 = true; // 至少有一个是J或空位 if ((hasJ1 || hasJ2) || (map[x1][y1] == 0 || map[x2][y2] == 0)) { int d = (jPoints[i].x-jPoints[k].x)*(jPoints[i].x-jPoints[k].x) + (jPoints[i].y-jPoints[k].y)*(jPoints[i].y-jPoints[k].y); if (d > maxArea) maxArea = d; } } // 计算另一种可能的正方形 int x3 = jPoints[i].x - (jPoints[i].y - jPoints[k].y); int y3 = jPoints[i].y - (jPoints[k].x - jPoints[i].x); int x4 = jPoints[k].x - (jPoints[i].y - jPoints[k].y); int y4 = jPoints[k].y - (jPoints[k].x - jPoints[i].x); // 检查第二种可能的正方形 bool valid2 = (x3 >= 1 && x3 <= n && y3 >= 1 && y3 <= n) && (x4 >= 1 && x4 <= n && y4 >= 1 && y4 <= n); if (valid2) { bool hasJ3 = false, hasJ4 = false; if (map[x3][y3] == 1) hasJ3 = true; if (map[x4][y4] == 1) hasJ4 = true; // 至少有一个是J或空位 if ((hasJ3 || hasJ4) || (map[x3][y3] == 0 || map[x4][y4] == 0)) { int d = (jPoints[i].x-jPoints[k].x)*(jPoints[i].x-jPoints[k].x) + (jPoints[i].y-jPoints[k].y)*(jPoints[i].y-jPoints[k].y); if (d > maxArea) maxArea = d; } } } } printf("%d\n", maxArea); return 0; }
解决这个问题的核心在于如何判断四个点是否能构成正方形。对于任意四个点,我们可以通过计算它们之间的距离来判断:
正方形有 4 条相等的边和 2 条相等的对角线 对角线长度是边长的√2 倍,因此对角线长度的平方是边长平方的 2 倍
算法步骤如下:
读取输入并记录所有 'J' 的位置和可放置位置 检查仅由现有 'J' 构成的正方形 检查包含新放置 Bessie 的正方形 找出所有可能正方形中的最大面积
- 1
信息
- ID
- 2252
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者