codeforces 159 D(幾何二分)
阿新 • • 發佈:2018-11-05
題意:給你n個點,問與x軸相切,並且包含這n個點的圓的最小半徑是多少。
思路:真是做的的懷疑人生。思路是首先判斷點是否在一邊。
如果在一邊一定有解,二分半徑R,這時候圓心在y=R的線上,對於每個點,
我們移動圓就會發現包含這個點嗎圓心軌跡是一個線段,我們只需要對每個點的區域
交集,就可以判斷存不存在圓心。
但是奇怪的是,本地跟評測機跑的不一樣,還有一點不明白的是,
在二分的時候為什麼用精度會t,而需要直接設定迴圈次數。
精度1e-10,這樣複雜度是log(1e28)也就100次迴圈啊,不是很理解
#include<bits/stdc++.h> using namespace std; const int N=1e5+10; const double eps=1e-10; const double INF=1e18; struct Point{ double x, y; }p[N]; int n; bool check(double R){ double l=-1e9, r=1e9; for(int i=1; i<=n; i++){ if(p[i].y>2.0*R)return false; double d=p[i].y-R; double dx; dx=sqrt(R+d)*sqrt(R-d); l=max(l, p[i].x-dx), r=min(r, p[i].x+dx); if(l>r) return false; } return true; } int main(){ scanf("%d", &n); bool up=false, down=false; for(int i=1; i<=n; i++){ scanf("%lf%lf", &p[i].x, &p[i].y); if(p[i].y>0) up=true; else{ down=true; p[i].y=-p[i].y; } } if(up&&down){ puts("-1"); return 0; } double l=0, r=INF, ans=-1; for(int i=1; i<=300; i++){ double mid=(l+r)/2.0; if(check(mid)){ ans=mid; r=mid; } else{ l=mid; } } printf("%.10lf\n", ans); return 0; }