题意:一个圆与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;
}