• [luogu1742]最小圆覆盖


    考虑维护包含前$i$个点的最小圆,并不断加入下一个点——

    若加入的点被该圆包含,显然答案不变,否则该点必然在新的最小圆边界上

    换言之,此时得到了一个确定边界上某点的子问题,并用类似的方式处理

    以此类推,当第$3$轮中出现此情况时,即得到了圆边界上的三点,进而解出该圆

    具体的,以距离圆心相等建立方程,化简后为二元一次方程组

    同时,注意到更新后圆上至多含有$3$点,因此第$i$个点更新的概率不超过$\frac{3}{i}$

    归纳每一轮的复杂度均为$o(n)$,代入即$o(n)+\sum \frac{3}{i}o(i)=o(n)$,显然成立

    时间复杂度为$o(n)$(期望),可以通过

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 #define eps 1e-9
     5 int n;mt19937 rnd(0);
     6 struct Point{
     7     double x,y;
     8     Point operator + (const Point &k)const{
     9         return Point{x+k.x,y+k.y};
    10     }
    11     Point operator - (const Point &k)const{
    12         return Point{x-k.x,y-k.y};
    13     }
    14     Point operator * (const double &k)const{
    15         return Point{x*k,y*k};
    16     }
    17     double operator * (const Point &k)const{
    18         return x*k.y-y*k.x;
    19     }
    20     double len(){
    21         return sqrt(x*x+y*y);
    22     }
    23     double Len(){
    24         return x*x+y*y;
    25     }
    26 }a[N];
    27 struct Circle{
    28     double r;Point o;
    29     bool check(Point &k){
    30         return (o-k).len()<=r+eps;
    31     }
    32 }ans;
    33 Circle get_cir(Point &a,Point &b){
    34     return Circle{(a-b).len()/2,(a+b)*0.5};
    35 }
    36 Circle get_cir(Point &a,Point &b,Point &c){
    37     Point A=(b-a)*2,B=(c-a)*2;double s=1/(A*B);
    38     Point C=Point{b.Len()-a.Len(),c.Len()-a.Len()};
    39     Point o=Point{C*Point{A.y,B.y},Point{A.x,B.x}*C}*s;
    40     return Circle{(o-a).len(),o};
    41 }
    42 int main(){
    43     scanf("%d",&n);
    44     for(int i=1;i<=n;i++)scanf("%lf%lf",&a[i].x,&a[i].y);
    45     shuffle(a+1,a+n+1,rnd);
    46     for(int i=1;i<=n;i++)
    47         if (!ans.check(a[i])){
    48             ans=Circle{0,a[i]};
    49             for(int j=1;j<i;j++)
    50                 if (!ans.check(a[j])){
    51                     ans=get_cir(a[i],a[j]);
    52                     for(int k=1;k<j;k++)
    53                         if (!ans.check(a[k]))ans=get_cir(a[i],a[j],a[k]);
    54                 }
    55         }
    56     printf("%.9f\n%.9f %.9f\n",ans.r,ans.o.x,ans.o.y);
    57     return 0;
    58 }
    View Code
  • 相关阅读:
    【poj2761】 Feed the dogs
    【bzoj1086】 scoi2005—王室联邦
    学堂在线
    【bzoj3757】 苹果树
    【uoj58】 WC2013—糖果公园
    博弈论学习笔记
    【poj2960】 S-Nim
    【poj2234】 Matches Game
    【poj1740】 A New Stone Game
    【bzoj1853】 Scoi2010—幸运数字
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/16479092.html
Copyright © 2020-2023  润新知