zoukankan      html  css  js  c++  java
  • BZOJ 1337: 最小圆覆盖1336: [Balkan2002]Alien最小圆覆盖(随机增量法)

    今天才知道有一种东西叫随机增量法就来学了= =

    挺神奇的= =

    A.令ci为包括前i个点的最小圆,若第i+1个点无法被ci覆盖,则第i+1个点一定在ci+1上

    B.令ci为包括前i个点的最小圆且p在边上,若第i+1个点无法被ci覆盖,则第i+1个点与点p一定在ci+1上

    C.令ci为包括前i个点的最小圆且p,q在边上,若第i+1个点无法被ci覆盖,则第i+1个点与点p,q一定在ci+1上

    这样就确定一个圆了

    这样看上去是O(n^3)的,但是注意这个名字= =随机,说明我们能通过随机使其降到O(n)

    首先C显然是线性

    那么B-》c呢?对于一个点pi,在院内的概率是(i-1)/i在圆外的概率是1/i(因为这些点是随机的= =) 所以加入的复杂度为(i-1)/i*O(1)+1/i*O(i);

    A-》B同理,因此该算法的时间复杂度为线性的

    随机化多么神奇啊= =

    c++可以直接random_shuffle(STL多么神奇!!!)来随机化数组

    CODE:

    #include<cstdio>

    #include<iostream>

    #include<cstring>

    #include<algorithm>

    #include<cmath>

    using namespace std;

    #define sqr(x) ((x)*(x))

    #define fi first

    #define se second

    #define maxn 100100

    typedef pair<double,double> ii;

    ii a[maxn],cir;

    double r;

    double dis(ii x,ii y) {

    return sqrt(sqr(x.fi-y.fi)+sqr(x.se-y.se));

    }

    ii getcir(ii x,ii y,ii z){

    double a=sqr(x.fi)-sqr(y.fi)+sqr(x.se)-sqr(y.se),

      b=sqr(x.fi)-sqr(z.fi)+sqr(x.se)-sqr(z.se),

      c=2*(x.se-z.se)*(x.fi-y.fi)-2*(x.se-y.se)*(x.fi-z.fi);

    return ii((a*(x.se-z.se)-b*(x.se-y.se))/c,

    (a*(x.fi-z.fi)-b*(x.fi-y.fi))/(-c));

    }

    #define exp 1e-10

    int cmp(double x) {

    if (x<-exp) return -1;

    if (x>exp) return 1;

    return 0;

    }

    int n;

    int main(){

    scanf("%d",&n);

    for (int i=1;i<=n;i++) scanf("%lf%lf",&a[i].fi,&a[i].se);

    random_shuffle(a+1,a+1+n);

    cir=a[1],r=0;

    for (int i=1;i<=n;i++) {

    if (cmp(dis(cir,a[i])-r)<=0) continue;

    cir=a[i],r=0;

    for (int j=1;j<i;j++) {

    if (cmp(dis(cir,a[j])-r)<=0) continue;

    cir.fi=(a[i].fi+a[j].fi)/2,cir.se=(a[i].se+a[j].se)/2;

    r=dis(cir,a[j]);

    for (int k=1;k<j;k++) {

    if (cmp(dis(cir,a[k])-r)<=0) continue;

    cir=getcir(a[i],a[j],a[k]);

    r=dis(cir,a[i]);

    }

    }

    }

    printf("%lf %lf %lf ",r,cir.fi,cir.se);

    return 0;

    }


  • 相关阅读:
    Vasya and Endless Credits CodeForces
    Dreamoon and Strings CodeForces
    Online Meeting CodeForces
    数塔取数 基础dp
    1001 数组中和等于K的数对 1090 3个数和为0
    1091 线段的重叠
    51nod 最小周长
    走格子 51nod
    1289 大鱼吃小鱼
    POJ 1979 Red and Black
  • 原文地址:https://www.cnblogs.com/New-Godess/p/4348898.html
Copyright © 2011-2022 走看看