zoukankan      html  css  js  c++  java
  • BZOJ2280 : [Poi2011]Plot

    二分答案,转化为判定能否划分成不超过m段,且对每段求最小圆覆盖得到的圆半径不超过mid。

    对于当前的i,倍增出一个j,使得[i,i+(1<<j)-1]区间恰好不满足条件,然后在[i+(1<<(j-1))-1,i+(1<<j)-1]区间二分查找最大的t,使得[i,t]满足条件,然后划为一段。

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

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #define N 100010
    using namespace std;
    int n,m,i,T=50,cnt,ans[N][2];
    double l,r,mid,R,eps=1e-10;
    struct P{double x,y;}b[N],a[N],O;
    inline double dis(P x,P y){return sqrt((x.x-y.x)*(x.x-y.x)+(x.y-y.y)*(x.y-y.y));}
    inline P center(P x,P y,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 void cal(int l,int r){
      int i,j,k,n=0;
      for(i=l;i<=r;i++)a[n++]=b[i];
      for(i=0;i<n;i++)swap(a[rand()%n],a[i]);
      for(O=a[0],R=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)for(O=(P){(a[i].x+a[j].x)/2,(a[i].y+a[j].y)/2},R=dis(O,a[i]),k=0;k<j;k++)if(dis(a[k],O)>R+eps)O=center(a[k],a[j],a[i]),R=dis(O,a[i]);
    }
    inline bool check(double x){
      int i,j,l,r,mid,t,now=0;
      for(i=1;i<=n;i=t+1){
        for(j=1;i+(1<<j)-1<=n;j++){
          cal(i,i+(1<<j)-1);
          if(R>x+eps)break;
        }
        t=i,l=i+(1<<(j-1))-1,r=i+(1<<j)-1;
        if(r>n)r=n;
        while(l<=r){
          cal(i,mid=(l+r)>>1);
          if(R<x+eps)l=(t=mid)+1;else r=mid-1;
        }
        if((++now)>m)return 0;
      }
      return 1;
    }
    inline void fin(double x){
      int i,j,l,r,mid,t;
      for(i=1;i<=n;i=t+1){
        for(j=1;i+(1<<j)-1<=n;j++){
          cal(i,i+(1<<j)-1);
          if(R>x+eps)break;
        }
        t=i,l=i+(1<<(j-1))-1,r=i+(1<<j)-1;
        if(r>n)r=n;
        while(l<=r){
          cal(i,mid=(l+r)>>1);
          if(R<x+eps)l=(t=mid)+1;else r=mid-1;
        }
        ans[++cnt][0]=i,ans[cnt][1]=t;
      }
    }
    int main(){
      scanf("%d%d",&n,&m);
      for(i=1;i<=n;i++)scanf("%lf%lf",&b[i].x,&b[i].y);
      cal(1,n);
      r=R;
      if(m>1)while(T--&&r-l>eps)if(check(mid=(l+r)/2))r=mid;else l=mid;
      printf("%.8f
    ",r);
      fin(r);
      printf("%d
    ",cnt);
      for(i=1;i<=cnt;i++)cal(ans[i][0],ans[i][1]),printf("%.8f %.8f
    ",O.x,O.y);
      return 0;
    }
    

      

  • 相关阅读:
    Django 的 CSRF 保护机制
    uni横向滑动
    uni模板
    下载excel文件,链接,通过按钮点击创建a标签实现
    vue去除input输入框空格适用于搜索查询框
    整理个人笔记Linux的一些常用命令
    简单概括一下JAVA中的ANT的配置
    谈谈JavaIO System对IO的三种支持
    JAVA使用类库对数组和各种Collection容器进行排序
    c语言自行设计矩形类构造函数
  • 原文地址:https://www.cnblogs.com/clrs97/p/4713604.html
Copyright © 2011-2022 走看看