top1编程
← 返回题目
题解

防护伞

1 条题解

  • 0
    @ 2026-8-6 0:09:19

    P4699 防护伞(【基础】)

    解题思路

    伞心必须放在某一个黑子上。对每个黑子,把它当成圆心,计算它到所有黑子的最大距离的平方,这个最大值就是罩住全部黑子所需的半径平方。遍历所有黑子当圆心,取半径平方最小的那一个,再用面积公式算伞的面积。下面分四步实现。

    **第一步,读入。**读入 n 和 n 个黑子的坐标,分别存进 coordX、coordY 数组。

    **第二步,枚举圆心。**对每个黑子 i 当圆心,两重循环计算它到其他所有黑子 j 的距离平方 distSq = dx×dx + dy×dy(dx、dy 是两个坐标的差),取其中的最大值 maxDistSq。这个值就是以 i 为圆心罩住所有点的最小半径平方。

    **第三步,取最优圆心。**在所有黑子里,取 maxDistSq 最小的那个作为 bestDistSq。注意第一个黑子要先把 bestDistSq 设成它的 maxDistSq,再和后面的比较。

    **第四步,算面积。**面积 = π × 半径²,其中半径 = sqrt(bestDistSq),π 取 3.1415926535,输出保留 4 位小数,用 fixed + setprecision(4)。

    注意:黑子坐标可能达到 10 亿级别,两个点距离的平方会非常大,所以一定要用 long long 来存,防止溢出;最终面积用 double 计算即可。

    参考代码

    // P4699 防护伞:把伞心定在某个黑子上,求能罩住所有黑子的最小圆面积
    #include <iostream>
    #include <iomanip>
    #include <cmath>
    using namespace std;
    
    int main() {
        int n;
        cin >> n;
        long long coordX[1005], coordY[1005];
        for (int i = 0; i < n; i++) cin >> coordX[i] >> coordY[i];
        // 对每个黑子作为圆心,计算到所有点的最大距离平方,取其中的最小值
        long long bestDistSq = 0;
        for (int i = 0; i < n; i++) {
            long long maxDistSq = 0;
            for (int j = 0; j < n; j++) {
                long long dx = coordX[i] - coordX[j];
                long long dy = coordY[i] - coordY[j];
                long long distSq = dx * dx + dy * dy;
                if (distSq > maxDistSq) maxDistSq = distSq;
            }
            if (i == 0 || maxDistSq < bestDistSq) bestDistSq = maxDistSq;
        }
        // 半径取sqrt(bestDistSq),面积=3.1415926535*半径²,保留4位小数
        double radius = sqrt((double)bestDistSq);
        double area = 3.1415926535 * radius * radius;
        cout << fixed << setprecision(4) << area << endl;
        return 0;
    }
    

    复杂度分析

    对每个黑子都要计算它到其余所有黑子的距离,时间复杂度 O(N²)。N 最大几百,完全没问题。空间上只需要存每个点的坐标,是 O(N)。

    • 1