Codeforces Round #514 (Div. 2) D Nature Reserve(二分)

题意:一个圆与X轴相切,问最小的半径,使得圆包含所有给定的点。

思路:因为圆是y轴xi相切的,设半径为R,所以圆心肯定在y=R上,以每个点为圆心作半径为R的圆与y=R交于l和r,那么要求的圆的圆心肯定在这个区间,那么枚举每一个点的l和r,这样就可以一直缩小l和r的范围,最后如果l<r,也就是存在这样一个圆心。所以可以考虑二分枚举R。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const int maxn=100005;
const double eps=1e-8;
const double PI = acos(-1.0);
#define lowbit(x) (x&(-x))
ll gcd(ll a,ll b)
{
    return b==0?a:gcd(b,a%b);
}
int n;
struct point
{
    double x,y;
};
point p[maxn];
bool check(double k)
{
    double l=-1e18,r=1e18;
    for(int i=0;i<n;i++)
    {
        if(p[i].y>2*k)
            return 0;
        double t=sqrt(k-(k-p[i].y))*sqrt(k+(k-p[i].y));
        l=max(l,p[i].x-t);
        r=min(r,p[i].x+t);
    }
    return l<r;
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for(int i=0;i<n;i++)
    {
        cin>>p[i].x>>p[i].y;
    }
    for(int i=1;i<n;i++)
    {
        if(p[i].y*p[0].y<0)
        {
            cout<<-1<<endl;
            return 0;
        }
        else
            p[i].y=fabs(p[i].y);
    }
    p[0].y=fabs(p[0].y);
    double l=0,r=1e18,m,ans;
    for(int i=0;i<150;i++)
    {
        m=(l+r)/2;
        if(check(m))
        {
            ans=m;
            r=m;
        }
        else
            l=m;
    }
    printf("%.10lf\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Dilly__dally/article/details/83035829
今日推荐