cf 744D

给你红点蓝点,找一个最大的圆,圆里没有蓝点并且至少有一个红点。边界可算可不算。

一开始没看懂题解,想了好久(一整天)才想明白是枚举弦上点二分半径check角度,看了下clj的代码发现思路都一样就开始写了。

借鉴了一下clj的代码。

调了一个多小时。

几个注意点:看到好多 random_shuffle 的,我没有,也感觉没什么必要。(另外cjl的代码去掉random_shuffle好像会WA。。。)

极角排序之后可能会遇到很多很多点全在一个角上,这个时候如果排序的话会麻烦,比方说我们要先减后加(哪里麻烦了啊???)

所以我每次check是不是扫完了完整的一段,也可以理解成我们扫角度不扫点。

小优化,每次二分先check ans,然后把l设成ans。

关于怎么求角的范围:两个圆夹起来就是了,初中解析几何?

千万不要把二分的eps设成1e-8,不然你会在test5tle到自闭并且还根本不知道哪里T了。

(感冒摸了三天鱼了。不过这题收获还蛮大的)

 

  1 #include <bits/stdc++.h>
  2 #define rep(x) for(int i=0;i<x;i++)
  3 #define mk(a,b) make_pair(a,b)
  4 using namespace std;
  5 typedef double db;
  6 const db eps=1e-6;
  7 const db pi=acos(-1);
  8 int sign(db k){
  9     if (k>eps) return 1; else if (k<-eps) return -1; return 0;
 10 }
 11 int cmp(db k1,db k2){return sign(k1-k2);}
 12 struct point{
 13     db x,y;
 14     point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
 15     point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
 16     point operator * (db k1) const{return (point){x*k1,y*k1};}
 17     point operator / (db k1) const{return (point){x/k1,y/k1};}
 18     int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;}
 19     // 逆时针旋转
 20     point turn(db k1){return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
 21     bool operator < (const point k1) const{
 22         int a=cmp(x,k1.x);
 23         if (a==-1) return 1; else if (a==1) return 0; else return cmp(y,k1.y)==-1;
 24     }
 25     db abs(){return sqrt(x*x+y*y);}
 26     db abs2(){return x*x+y*y;}
 27     db dis(point k1){return ((*this)-k1).abs();}
 28     db getw(){return atan2(y,x);}
 29     int getP() const{return sign(y)==1||(sign(y)==0&&sign(x)==-1);}
 30 };
 31 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;}
 32 db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;}
 33 db slove(db S){
 34     if(S<0)S+=2*pi;
 35     else if(S>=2*pi) S-=2*pi;
 36     return S;
 37 }
 38 point r[1005],b[1005];
 39 vector<point> p;
 40 int n,m;
 41 vector<pair<db,int>> g;
 42 bool check(int id,db R){
 43     g.clear();
 44     point o = p[id];
 45     rep(n+m){
 46         if(i==id)continue;
 47         point tmp = p[i];
 48         db d = tmp.dis(o);
 49         if(cmp(d,R*2)>=0)continue;
 50         db alf = acos(d/2/R);
 51         db delta = atan2(tmp.y-o.y,tmp.x-o.x);
 52         db l = slove(delta-alf),r=slove(delta+alf);
 53         if(l<r){
 54             g.push_back(mk(l,i<n?2:1));
 55             g.push_back(mk(r,-(i<n?2:1)));
 56         }else{
 57             g.push_back(mk(l,i<n?2:1));
 58             g.push_back(mk(2*pi,-(i<n?2:1)));
 59             g.push_back(mk(0,i<n?2:1));
 60             g.push_back(mk(r,-(i<n?2:1)));
 61         }
 62     }
 63     if(id<n)g.push_back(mk(0,id<n?2:1)),g.push_back(mk(2*pi,-(id<n?2:1)));
 64     sort(g.begin(),g.end());
 65     int rn=0,bn=0;
 66     rep(g.size()){
 67         if((i==g.size()-1||g[i].first!=g[i+1].first)&&rn>0&&bn<=0)return true;
 68         if(abs(g[i].second)==1)
 69             bn+=g[i].second;
 70         else
 71             rn+=g[i].second/2;
 72     }
 73     return false;
 74 }
 75 //枚举弦上点,二分半径,check角度范围,判断是否可行
 76 int main(){
 77     //freopen("zibi.in","r",stdin);
 78     scanf("%d%d",&n,&m);
 79     rep(n) scanf("%lf%lf",&r[i].x,&r[i].y),p.push_back(r[i]);
 80     rep(m) scanf("%lf%lf",&b[i].x,&b[i].y),p.push_back(b[i]);
 81     bool f=0;
 82     rep(n+m)
 83         if(check(i,1e15))
 84             //return 0*printf("%d -1\n",i);
 85             return 0*printf("-1\n");
 86     db ans = 0;
 87     //random_shuffle(p.begin(),p.begin()+n);
 88     //random_shuffle(p.begin()+n,p.end());
 89     for(int i=0;i<n+m;i++){
 90         db l=ans,r=1e9;
 91         if(check(i,ans)) {
 92             while (l + eps < r) {
 93                 db mid = (l + r) / 2;
 94                 if (check(i, mid))
 95                     l = mid;
 96                 else r = mid;
 97             }
 98             ans = l;
 99            // printf("%d %.11f\n",i,ans);
100         }
101     }
102     printf("%.11f\n",ans);
103 }
104 /**
105 
106  */
107 /**
108 
109  */
View Code

 

 

 

 

 


posted @ 2019-04-04 14:29  MXang  阅读(251)  评论(0编辑  收藏  举报