1 条题解

  • 0
    @ 2025-6-16 17:35:26
    #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
    上传者