codeforces round514 D Natural reserve(简单几何+二分)

本文探讨了一道几何问题,即如何找到一个与x轴相切并包含所有给定点的圆,使得该圆的半径最小。通过二分搜索算法确定圆心位置,确保所有点位于圆内。文章提供了详细的算法解释及C++实现代码。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意

坐标轴中有nnn个点,需要画一个圆,这个人与xxx轴相切,且包含全部的nnn个点,问这个圆的半径最小是多少。

题解

二分搜索半径,观察可以发现,这个圆的圆心一定是在y=Ry = Ry=R上面移动的,所以我们可以依据这个半径确定每个点的圆心在y=Ry=Ry=R这条线上的范围,如果所有的点的圆心的范围有交集,那么这个RRR就是符合条件的。
对于一个点,其可能的圆心范围是 l=x−R2−(y−R)2,r=l=x+R2−(y−R)2l = x-\sqrt{R^2-(y-R)^2}, r =l = x+\sqrt{R^2-(y-R)^2}l=xR2(yR)2,r=l=x+R2(yR)2,需要判断一下根号下为负数的情况,还有直接R∗RR*RRR会爆精度,需要化简一下。

代码

#include <iostream>
#include <cmath>
using namespace std;
const int maxn = 1e5+5;
const double EPS = 1e-8;
int n;
struct Node {
    double x,y;
}cor[maxn];

bool ok(double x) {
    double l = -1e10, r = 1e10;
    for(int i = 0; i < n; ++i) {
        double h = abs(cor[i].y-x);
        if(h > x) return 0;
        double range = sqrt(cor[i].y*(2*x-cor[i].y));
        l = max(l, cor[i].x-range), r = min(r, cor[i].x+range);
    }
    return (r-l)>EPS;
}
int main() {
    scanf("%d", &n);
    bool fg1 = false, fg2 = false;
    for(int i = 0; i < n; ++i) {
        scanf("%lf%lf", &cor[i].x, &cor[i].y);
        if(cor[i].y < 0)
            fg1 = true, cor[i].y = -cor[i].y;
        else 
            fg2 = true;
    }
    if(fg1 && fg2) {
        puts("-1");
    }
    else if(n == 1) {
        printf("%lf\n", cor[0].y/2);
    }
    else {
        double l = 0, r = 1e18, ans;
        for(int i = 0; i < 1000; ++i) {
            double mid = (l+r)/2;
         //   cout << mid << endl;
            if(ok(mid)) {
                r = mid;
                ans = mid;
            }
            else l = mid;
        }
        printf("%lf\n", ans);
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值