最小覆盖圆

给出一堆点,求一个面积(半径)最小的圆,使得所有点都在它的内部或边界上.

随机增量法是这样的....

先随机打乱点的顺序......

然后,我们假设已经得到了点 $1,2,...,i$ 的最小覆盖圆,我们要求出点 $1,2,...,i,i+1$ 的最小覆盖圆.

怎么做? 考虑点 $i+1$ ,分两种情况:

1.如果点 $i+1$ 在点 $1,2,...,i$ 的最小覆盖圆里面或边界上,那么点 $1,2,...,i,i+1$ 的最小覆盖圆就是点 $1,2,...,i$ 的最小覆盖圆.

证明:

  假设点 $1,2,...,i,i+1$ 的最小覆盖圆比点 $1,2,...,i$ 的最小覆盖圆小. 这意味着,我们可以用点 $1,2,...,i,i+1$ 的最小覆盖圆来覆盖点 $1,2,...,i$ ,因此我们找到了一个新的圆,它覆盖了点 $1,2,..,i$ 比 $1,2,...,i$ 的最小覆盖圆还要小.显然矛盾.

结合最小覆盖圆的唯一性可得出结论.

上述证明说明了,最小覆盖圆在我们依次添加点的过程中,面积(半径)一定单调不减的.

2.如果点 $i+1$ 在点 $1,2,...,i$ 的最小覆盖圆外,那么点 $i+1$ 一定在点 $1,2,...,i,i+1$ 的最小覆盖圆的边界上.

不会证!哪位神犇前来拯救我QAQ

有了这个性质以后,我们就可以按顺序来做"三点确定一个圆"的事情=.=

现在我们知道了点 $i+1$ 必定会在边界上. 那么我们再用一次这个方法:

假设我们已经得到了点 $1,2,...,j$ 的过点 $i+1$ 的最小覆盖圆. 现在我们要求点 $1,2,...,j,j+1$ 的,过点 $i+1$ 的最小覆盖圆. 如果点 $j+1$ 已经在那个最小覆盖圆里面,根据情况1可以将这个点忽略.如果不在,再用一次这个方法:

假设我们已经得到了点 $1,2,...,k$ 的,过两个点 $j+1,i+1$ 的最小覆盖圆. 现在我们要求点 $1,2,...,k,k+1$ 的,过点 $j+1,i+1$ 的最小覆盖圆. 如果点 $k+1$ 已经在那个最小覆盖圆里面,根据情况1可以将这个点忽略.如果不在,直接求三个点 $k+1,j+1,i+1$ 对应的外接三角形就是答案.

最后那句话不怎么理解QAQ......

另外怎么证明,最小覆盖圆只能有一个?

AC BZOJ 2823 裸的最小覆盖圆

  1 #include <cstdio>
  2 #include <fstream>
  3 #include <iostream>
  4
  5 #include <cstdlib>
  6 #include <cstring>
  7 #include <algorithm>
  8 #include <cmath>
  9
 10 #include <queue>
 11 #include <vector>
 12 #include <map>
 13 #include <set>
 14 #include <stack>
 15 #include <list>
 16
 17 typedef unsigned int uint;
 18 typedef long long int ll;
 19 typedef unsigned long long int ull;
 20 typedef double db;
 21 typedef long double ldb;
 22
 23 using namespace std;
 24
 25 inline int getint()
 26 {
 27     int res=0;
 28     char c=getchar();
 29     bool mi=false;
 30     while(c<‘0‘ || c>‘9‘) mi=(c==‘-‘),c=getchar();
 31     while(‘0‘<=c && c<=‘9‘) res=res*10+c-‘0‘,c=getchar();
 32     return mi ? -res : res;
 33 }
 34 inline ll getll()
 35 {
 36     ll res=0;
 37     char c=getchar();
 38     bool mi=false;
 39     while(c<‘0‘ || c>‘9‘) mi=(c==‘-‘),c=getchar();
 40     while(‘0‘<=c && c<=‘9‘) res=res*10+c-‘0‘,c=getchar();
 41     return mi ? -res : res;
 42 }
 43
 44 //==============================================================================
 45 //==============================================================================
 46 //==============================================================================
 47 //==============================================================================
 48
 49 db eps=1e-6;
 50
 51 struct point
 52 {
 53     db x,y;
 54     point(db x=0,db y=0):x(x),y(y){}
 55     point operator+(point f) { return point(x+f.x,y+f.y); }
 56     point operator*(db f) { return point(x*f,y*f); }
 57     point operator*(point f) { return x*f.y-y*f.x; }
 58     point operator-(point f) { return point(x-f.x,y-f.y); }
 59     point operator()(point f) { return point(f.x-x,f.y-y); }
 60     point&operator=(point f) { memcpy(this,&f,sizeof(point)); return *this; }
 61 };
 62
 63 db dist(const point &a,const point &b)
 64 { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); }
 65
 66 point cc(point&a,point&b,point&c)
 67 {
 68     point ret;
 69     db a1=b.x-a.x,b1=b.y-a.y,c1=(a1*a1+b1*b1)*0.5;
 70     db a2=c.x-a.x,b2=c.y-a.y,c2=(a2*a2+b2*b2)*0.5;
 71     db d=a1*b2-a2*b1;
 72     if(abs(d)<1e-12) return (b+c)*0.5;
 73     ret.x=a.x+(c1*b2-c2*b1)/d;
 74     ret.y=a.y+(a1*c2-a2*c1)/d;
 75     return ret;
 76 }
 77
 78 int n;
 79 point a[1005000];
 80
 81 void putres(db a,db b,db r)
 82 {printf("%.2f %.2f %.2f\n",a,b,r);}
 83
 84 int main()
 85 {
 86     srand(23333);
 87
 88     n=getint();
 89     for(int i=0;i<n;i++)
 90     scanf("%lf%lf",&a[i].x,&a[i].y);
 91
 92     if(n==0) { putres(0,0,0); return 0; }
 93     if(n==1) { putres(a[0].x,a[0].y,0); return 0; }
 94     if(n==2)
 95     {
 96         putres( (a[0]+a[1]).x*0.5,
 97                  (a[0]+a[1]).y*0.5,
 98                   dist(a[0],a[1])*0.5);
 99
100         return 0;
101     }
102
103     for(int i=0;i<n;i++)
104     {
105         int p=rand()%n;
106         swap(a[i],a[p]);
107     }
108     point O; db R=0.0;
109     for(int i=2;i<n;i++)
110     if(dist(a[i],O)>=R+eps)
111     {
112         O=a[i];
113         R=0.0;
114
115         for(int j=0;j<i;j++)
116         if(dist(a[j],O)>=R+eps)
117         {
118             O=(a[i]+a[j])*0.5;
119             R=dist(a[i],a[j])*0.5;
120
121             for(int k=0;k<j;k++)
122             if(dist(a[k],O)>=R+eps)
123             {
124                 O=cc(a[i],a[j],a[k]);
125                 R=dist(a[i],O);
126             }
127         }
128     }
129
130     putres(O.x,O.y,R);
131
132     return 0;
133 }

。。。

时间: 2024-11-09 04:01:37

最小覆盖圆的相关文章

Maple trees(最小覆盖圆)

Maple trees Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 222 Accepted Submission(s): 79   Problem Description There are a lot of trees in HDU. Kiki want to surround all the trees with the minim

zoj 1450 Minimal Circle 最小覆盖圆

题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=450 You are to write a program to find a circle which covers a set of points and has the minimal area. There will be no more than 100 points in one problem. 题意描述:找到一个最小圆能够包含到所有的二维坐标点. 算法

最小覆盖圆算法

最小圆覆盖,很经典的问题.题目大概是,平面上n个点,求一个半径最小的圆,能够覆盖所有的点. 算法有点难懂,于是讲讲我的理解. 如果要求一个最小覆盖圆,这个圆至少要由三个点确定.有一种算法就是任意取三个点作圆,然后判断距离圆心最远的点是否在圆内,若在,则完成:若不在则用最远点更新这个圆. 这里介绍的算法是,先任意选取两个点,以这两个点的连线为直径作圆.再以此判断剩余的点,看它们是否都在圆内(或圆上),如果都在,说明这个圆已经找到.如果没有都在:假设我们用的最开始的两个点为p[1],p[2],并且找

hdu2215(最小覆盖圆)

Maple trees Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1578    Accepted Submission(s): 488 Problem Description There are a lot of trees in HDU. Kiki want to surround all the trees with the

(hdu step 7.1.5)Maple trees(求凸包的最小覆盖圆的半径)

题目: Maple trees Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 177 Accepted Submission(s): 63   Problem Description There are a lot of trees in HDU. Kiki want to surround all the trees with the m

[matlab] 10.最小覆盖圆

clear all; close all; clc; n=100; p=rand(n,2); p1=p(1,:); %取第一行的值 P1点 p2=p(2,:); %取第二行的值 P2点 r=sqrt((p1(1)-p2(1))^2+(p1(2)-p2(2))^2)/2; %求两点半径 cenp=(p1+p2)/2; %求两点中点 for i=3:n newp=p(i,:); %从第三行开始 储存新的点 d=sqrt((cenp(1)-newp(1))^2+(cenp(2)-newp(2))^2)

平面点集的最小包围圆 hdu 3932

最小覆盖圆算法地址:http://soft.cs.tsinghua.edu.cn/blog/?q=node/1066 平面点集的最小包围圆 1.           问题背景 考察固定在工作平台上的一直机械手,要捡起散落在不同位置的多个零件,并送到别的地方.那么,这只机械手的底座应该选在哪里呢?根据直觉,应该选在机械手需够着的那些位置的"中心".准确地讲,也就是包围这些点的那个最小圆的圆心----该位置的好处是,可使机械手的底座到它需要够着的那些点的最大距离最小化.于是可得如下问题:给

计算几何学习8

由于poj炸了 而题单上有很多poj的题 就先开始第二部分了 学习了两个固定算法 最小圆覆盖和平面上最近点对 平面上最近点对采用的是分治的思想 把一个x有序的序列分成A,B左右两部分 当得到A内最近点对距离,B类最近点对距离后 先更新大序列的答案ans A,B间最近点对的产生 显然在x坐标距离mid点不超过ans的区间内产生 我们把这段区间拿出来,对y排序 再逐对更新 值得注意的地方 1)为了确保速度 可以在第二次对y排序的时候采取对标号排序的方式 2)在枚举点对更新的时候注意在y差值 >= a

计算几何及其应用——解析几何

写在前面:刚学专业课的时候,记得有天突发奇想,心说高三数学的压轴题能不能写个程序跑出答案,这样岂不是解放了数万苦逼高三生的双手?但是当时也仅仅是停留在想法上面,因为高中的解析几何虽然步骤程序化,但是有时候需要灵巧的因式分解,感觉以目前的编程水平还是写不出来,但是了解到数学有一个分支——计算几何,专门利用计算机来进行几何计算的一门科学,并且还与计算机图形学.计算机视觉和图像处理.机器人.计算机辅助设计和制造等高深学科有着联系(摘自<计算几何与应用>导言),所以今天怀着激动的心情开始了这个专题的学