zoukankan      html  css  js  c++  java
  • 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
    ",i);
     85             return 0*printf("-1
    ");
     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
    ",i,ans);
    100         }
    101     }
    102     printf("%.11f
    ",ans);
    103 }
    104 /**
    105 
    106  */
    107 /**
    108 
    109  */
    View Code
    
    
  • 相关阅读:
    Add函数求两个数的和,不能使用+号或其它算术运算符
    小刘同学的第八十六篇博文
    小刘同学的第八十五篇博文
    小刘同学的第八十四篇博文
    小刘同学的第八十三篇博文
    小刘同学的第八十二篇博文
    小刘同学的第八十一篇博文
    小刘同学的第八十篇博文
    小刘同学的第七十九篇博文
    小刘同学的第七十八篇博文
  • 原文地址:https://www.cnblogs.com/MXang/p/10654677.html
Copyright © 2011-2022 走看看