题解: [蓝桥杯 2024 国 Python A/Java A/Java 研究生] 汉字田
源题目地址:https://www.lanqiao.cn/problems/20122/learning/
题目分析
这道题目要求我们计算在"田"字形排列的9个点中,有多少条直线恰好只经过其中的两个点。我们需要考虑所有可能的点对,并检查是否有其他点也在这条直线上。
解题思路
- 坐标设定:将"田"字形的9个点坐标化,中心为(0,0),其他点分布在坐标轴上。
- 遍历所有点对:检查每两个点确定的直线。
- 共线性检查:对于每对点确定的直线,检查是否有其他点也在这条直线上。
- 计数:统计满足条件的直线数量。
代码实现
import java.util.ArrayList;
import java.util.List;
public class Main {
static class Point {
int x, y;
Point(int x, int y) {
this.x = x;
this.y = y;
}
}
// 检查点c是否在点a和点b确定的直线上
static boolean isCollinear(Point a, Point b, Point c) {
// 向量叉积为零表示共线
return (b.x - a.x) * (c.y - a.y) == (b.y - a.y) * (c.x - a.x);
}
public static void main(String[] args) {
// 定义9个点的坐标
List<Point> points = new ArrayList<>();
points.add(new Point(-1, 1)); // 左上
points.add(new Point(1, 1)); // 右上
points.add(new Point(-1, -1)); // 左下
points.add(new Point(1, -1)); // 右下
points.add(new Point(0, 1)); // 上中点
points.add(new Point(0, -1)); // 下中点
points.add(new Point(-1, 0)); // 左中点
points.add(new Point(1, 0)); // 右中点
points.add(new Point(0, 0)); // 中心
int count = 0;
// 遍历所有两点组合
for (int i = 0; i < points.size(); i++) {
for (int j = i + 1; j < points.size(); j++) {
Point a = points.get(i);
Point b = points.get(j);
boolean isValid = true;
// 检查是否有其他点在这条直线上
for (int k = 0; k < points.size(); k++) {
if (k == i || k == j) continue;
Point c = points.get(k);
if (isCollinear(a, b, c)) {
isValid = false;
break;
}
}
if (isValid) {
count++;
}
}
}
System.out.println(count);
}
}
复杂度分析
- 时间复杂度:O(n³),其中n=9是点的数量。因为需要检查所有点对,并对每个点对检查其他点是否共线。
- 空间复杂度:O(n),用于存储点的坐标。
算法特点
- 直观性:直接模拟问题,易于理解和实现。
- 准确性:通过向量叉积精确判断共线性。
- 完整性:检查所有可能的点对,确保不遗漏任何情况。
该解法能够准确计算出"田"字形排列的9个点中恰好只经过两个点的直线数量。