zoukankan      html  css  js  c++  java
  • BZOJ1946 : [Ceoi2006]ANTENNA

    首先通过随机增量法求出最小覆盖圆,作为答案的上界。

    然后二分答案,检验的时候枚举每个点作为原点,求出其他每个点被包括在圆内的角度区间,然后扫描线即可。

    时间复杂度$O(Tn^2log n)$。

    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<cstdlib>
    #define N 510
    using namespace std;
    const double PI=acos(-1.0),eps=1e-8;
    int n,K,i,j,k;double R,ansr,lim,l,r,mid;
    struct P{
      double x,y;
      P(){}
      P(double _x,double _y){x=_x,y=_y;}
    }a[N],O,anso;
    struct E{
      double x;int t;
      E(){}
      E(double _x,int _t){x=_x,t=_t;}
    }e[N<<2];
    inline bool cmp(const E&a,const E&b){return a.x<b.x;}
    inline double dis(const P&x,const P&y){
      return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));
    }
    inline P center(const P&x,const P&y,const P&z){
      double a1=y.x-x.x,b1=y.y-x.y,
             c1=(a1*a1+b1*b1)/2,a2=z.x-x.x,
             b2=z.y-x.y,c2=(a2*a2+b2*b2)/2,
             d=a1*b2-a2*b1;
      return P(x.x+(c1*b2-c2*b1)/d,x.y+(a1*c2-a2*c1)/d);
    }
    inline bool exist(int S,double R){
      int m=0;
      for(int i=0;i<n;i++)if(i!=S){
        if(dis(a[S],a[i])>R+R+eps)continue;
        double A=atan2(a[i].y-a[S].y,a[i].x-a[S].x),
               B=acos(dis(a[S],a[i])/(R+R));
        e[m++]=E(A-B,1);
        e[m++]=E(A+B,-1);
        e[m++]=E(A-B+PI*2,1);
        e[m++]=E(A+B+PI*2,-1);
      }
      sort(e,e+m,cmp);
      for(int i=0,ret=1;i<m;i++)if((ret+=e[i].t)==K){
        ansr=R;
        anso=P(a[S].x+cos(e[i].x)*R,a[S].y+sin(e[i].x)*R);
        return 1;
      }
      return 0;
    }
    inline bool check(double R){
      for(int i=0;i<n;i++)if(exist(i,R))return 1;
      return 0;
    }
    int main(){
      scanf("%d%d",&n,&K);
      for(i=0;i<n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
      for(i=0;i<n;i++)swap(a[rand()%n],a[i]);
      for(O=a[0],i=1;i<n;i++)if(dis(a[i],O)>R+eps)
        for(O=a[i],R=0,j=0;j<i;j++)if(dis(a[j],O)>R+eps){
          O=P((a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2),R=dis(a[i],O);
          for(k=0;k<j;k++)if(dis(a[k],O)>R+eps)O=center(a[k],a[j],a[i]),R=dis(a[i],O);
        }
      lim=ansr=R,anso=O;
      r=ansr-eps;
      while(l+eps<r){
        lim/=2;
        if(lim<1e-5)break;
        mid=(l+r)/2;
        if(check(mid))r=mid-eps;else l=mid+eps;
      }
      return printf("%.6f
    %.6f %.6f",ansr,anso.x,anso.y),0;
    }
    

      

  • 相关阅读:
    hdu 1823 Luck and Love 二维线段树
    UVA 12299 RMQ with Shifts 线段树
    HDU 4578 Transformation 线段树
    FZU 2105 Digits Count 线段树
    UVA 1513 Movie collection 树状数组
    UVA 1292 Strategic game 树形DP
    【ACM】hdu_zs2_1003_Problem C_201308031012
    qsort快速排序
    【ACM】nyoj_7_街区最短路径问题_201308051737
    【ACM】nyoj_540_奇怪的排序_201308050951
  • 原文地址:https://www.cnblogs.com/clrs97/p/5758892.html
Copyright © 2011-2022 走看看