CF1059D Nature Reserve(二分)

探讨了使用二分法求解包含N个点且与y轴相切的最小覆盖圆半径问题。通过判断所有点是否位于y轴同一侧来确定解的存在性,并详细解释了如何验证特定半径下能否包含所有点的方法。

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

简洁翻译:

有N个点,求与y=0相切的,包含这N个点的最小圆的半径

 

题解

二分半径右端点开小了结果交了二十几次都没A……mmp……

考虑一下,显然这个半径是可以二分的

再考虑一下,如果所有点都在y轴同一侧就有解,否则肯定无解

然后现在只要考虑在y轴同一侧时某一个半径是否能够包含所有点即可

因为得和y轴相切,所以半径确定时,圆心的y坐标是确定的

然后我们考虑对于每一个点,圆心的x坐标必须处在什么范围内

设这个点坐标为(x,y),圆半径为r,如果y>2*r显然不行

然后用勾股定理算一下两点之间的x坐标最多相差多少,那么就可以知道圆心的x坐标在什么范围内了

然后所有的范围并起来,如果是空集不可行,否则可行

然后注意判断x坐标相差多少时候的写法……代码里写了……

 1 //minamoto
 2 #include<bits/stdc++.h>
 3 using namespace std;
 4 template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
 5 template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
 6 const int N=2e5+5;
 7 int n,flag1=0,flag2=0;double l=0,r=1e18,ans=0,mx,x[N],y[N];
 8 bool check(double mid){
 9     double L=-1e18,R=1e18;
10     for(int i=1;i<=n;++i){
11         if(2*mid<y[i]) return false;
12         double len=sqrt(mid-(mid-y[i]))*sqrt(mid+(mid-y[i]));
13         //这里判断往左右能延伸多少时要这样写
14         //据说不这样写会导致严重的精度误差
15         //所以要先开方再相乘 
16         L=max(L,x[i]-len),R=min(R,x[i]+len);
17     }
18     return L<R;
19 }
20 int main(){
21     cin>>n;
22     for(int i=1;i<=n;++i){
23         cin>>x[i]>>y[i];
24         if(y[i]>0) flag1=1;
25         if(y[i]<0) flag2=1;
26     }
27     if(flag1&&flag2) return puts("-1"),0;
28     if(flag2){
29         for(int i=1;i<=n;++i) y[i]=-y[i];
30     }
31     int times=500;
32     while(times--){
33         double mid=(l+r)/2;
34         if(check(mid)) ans=mid,r=mid;
35         else l=mid;
36     }
37     printf("%.10lf\n",ans);
38     return 0;
39 }

 

转载于:https://www.cnblogs.com/bztMinamoto/p/9761260.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值