今天学习了一下最小圆覆盖, 看了一下午都没看懂, 晚上慢慢的摸索这代码,接合着别人的讲解, 画着图跟着代码一步一步的走着,竟然有些理解了.

最小圆覆盖: 给定n个点, 求出半径最小的圆可以把这些点全部包围, 可以在圆的边界上

下面是我的个人理解. 如果不对, 还请路过大牛指出

先找一个点, 让圆心等于这个点的坐标, 半径等于0, 显然这个对的, 接着找下一个点, 如果只有两个点的话, 那么最小的圆一定是以他们为直径做圆, 接着找第三个点, 如果第三个点在园内或者在边界上, 那么不用更新当前的最小圆, 如果不在的话, 就要更新当前的最小圆了,使它包括这三个点, 那么更新的办法就是从他开始做圆, 依次判断它前面的点是否满足在最小圆内, 如果不在的话, 就需要根据两个点或者三个点来确定圆了, 它的外接圆最多三个点就确定了,刚开始一直不理解这个为什么三个点,后来画画图,走走就出来了. 我这可能说的比较笼统. 表达能力太差. 还是把大牛的原话拷过来把.

最小覆盖圆, 增量法
假设圆O是前i-1个点得最小覆盖圆,加入第i个点,如果在圆内或边上则什么也不做。否,新得到的最小覆盖圆肯定经过第i个点。
然后以第i个点为基础(半径为0),重复以上过程依次加入第j个点,若第j个点在圆外,则最小覆盖圆必经过第j个点。
重复以上步骤(因为最多需要三个点来确定这个最小覆盖圆,所以重复三次)。遍历完所有点之后,所得到的圆就是覆盖所有点得最小圆。

证明可以考虑这么做:
最小圆必定是可以通过不断放大半径,直到所有以任意点为圆心,半径为半径的圆存在交点,此时的半径就是最小圆。所以上述定理可以通过这个思想得到。这个做法复杂度是O(n)的,当加入圆的顺序随机时,因为三点定一圆,所以不在圆内概率是3/i,求出期望可得是O(n)。

下面是代码(模板)

/*************************************************************************
> File Name: hdu_3007.cpp
> Author: Howe_Young
> Mail: 1013410795@qq.com
> Created Time: 2015年05月04日 星期一 18时42分33秒
************************************************************************/
/*最小圆覆盖*/
/*给定n个点, 让求半径最小的圆将n个点全部包围,可以在圆上*/
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#define EPS 1e-8
using namespace std;
const int maxn = ;
struct point{
double x, y;
};
int sgn(double x)
{
if (fabs(x) < EPS)
return ;
return x < ? - : ;
}
double get_distance(const point a, const point b)//两点之间的距离
{
return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
point get_circle_center(const point a, const point b, const point c)//得到三角形外接圆的圆心
{
point center;
double a1 = b.x - a.x;
double b1 = b.y - a.y;
double c1 = (a1 * a1 + b1 * b1) / 2.0;
double a2 = c.x - a.x;
double b2 = c.y - a.y;
double c2 = (a2 * a2 + b2 * b2) / 2.0;
double d = a1 * b2 - a2 * b1;
center.x = a.x + (c1 * b2 - c2 * b1) / d;
center.y = a.y + (a1 * c2 - a2 * c1) / d;
return center;
}
//p表示定点, n表示顶点的个数, c代表最小覆盖圆圆心, r是半径
void min_cover_circle(point *p, int n, point &c, double &r)//找最小覆盖圆(这里没有用全局变量p[], 因为是为了封装一个函数便于调用)
{
random_shuffle(p, p + n);//随机函数,使用了之后使程序更快点,也可以不用
c = p[];
r = ;
for (int i = ; i < n; i++)
{
if (sgn(get_distance(p[i], c) - r) > )//如果p[i]在当前圆的外面, 那么以当前点为圆心开始找
{
c = p[i];//圆心为当前点
r = ;//这时候这个圆只包括他自己.所以半径为0
for (int j = ; j < i; j++)//找它之前的所有点
{
if (sgn(get_distance(p[j], c) - r) > )//如果之前的点有不满足的, 那么就是以这两点为直径的圆
{
c.x = (p[i].x + p[j].x) / 2.0;
c.y = (p[i].y + p[j].y) / 2.0;
r = get_distance(p[j], c);
for (int k = ; k < j; k++)
{
if (sgn(get_distance(p[k], c) - r) > )//找新作出来的圆之前的点是否还有不满足的, 如果不满足一定就是三个点都在圆上了
{
c = get_circle_center(p[i], p[j], p[k]);
r = get_distance(p[i], c);
}
}
}
}
}
}
}
int main()
{
int n;
point p[maxn];
point c; double r;
while (~scanf("%d", &n) && n)
{
for (int i = ; i < n; i++)
scanf("%lf %lf", &p[i].x, &p[i].y);
min_cover_circle(p, n, c, r);
printf("%.2lf %.2lf %.2lf\n", c.x, c.y, r);
}
return ;
}

最小圆覆盖 hdu 3007的更多相关文章

  1. 【BZOJ-1336&1337】Alie最小圆覆盖 最小圆覆盖(随机增量法)

    1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special JudgeSubmit: 1573   ...

  2. Bzoj 1336&1337 Alien最小圆覆盖

    1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 Sec  Memory Limit: 162 MBSec  Special Judge Submit: 1473  ...

  3. hdu3007Buried memory(最小圆覆盖)

    链接 普通的暴力复杂度达到O(n^4),对于这题肯定是不行的. 解法:随机增量算法 参考http://www.2cto.com/kf/201208/149602.html algorithm:A.令C ...

  4. [BZOJ 3564] [SHOI2014] 信号增幅仪 【最小圆覆盖】

    题目链接:BZOJ - 3564 题目分析 求最小椭圆覆盖,题目给定了椭圆的长轴与 x 轴正方向的夹角,给定了椭圆长轴与短轴的比值. 那么先将所有点旋转一个角度,使椭圆长轴与 x 轴平行,再将所有点的 ...

  5. [BZOJ 1336] [Balkan2002] Alien最小圆覆盖 【随机增量法】

    题目链接:BZOJ - 1336 题目分析 最小圆覆盖有一个算法叫做随机增量法,看起来复杂度像是 O(n^3) ,但是可以证明其实平均是 O(n) 的,至于为什么我不知道= = 为什么是随机呢?因为算 ...

  6. bzoj1336: [Balkan2002]Alien最小圆覆盖

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1336 1336: [Balkan2002]Alien最小圆覆盖 Time Limit: 1 ...

  7. 【做题】POI2011R1 - Plot——最小圆覆盖&倍增

    原文链接 https://www.cnblogs.com/cly-none/p/loj2159.html 题意:给出\(n\)个点,你需要按编号将其划分成不超过\(m\)段连续的区间,使得所有每个区间 ...

  8. 【BZOJ2823】[AHOI2012]信号塔(最小圆覆盖)

    [BZOJ2823][AHOI2012]信号塔(最小圆覆盖) 题面 BZOJ 洛谷 相同的题: BZOJ1 BZOJ2 洛谷 题解 模板题... #include<iostream> #i ...

  9. BZOJ 3564: [SHOI2014]信号增幅仪 最小圆覆盖

    3564: [SHOI2014]信号增幅仪 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=3564 Description 无线网络基站在 ...

随机推荐

  1. 3.1决策树理论--python深度机器学习

    参考彭亮老师的视频教程:转载请注明出处及彭亮老师原创 视频教程: http://pan.baidu.com/s/1kVNe5EJ   0. 机器学习中分类和预测算法的评估:   准确率 速度 强壮行 ...

  2. cloudera目录位置

    http://www.aboutyun.com/thread-9189-1-1.html 这里来的嘿嘿. 1. 相关目录/var/log/cloudera-scm-installer : 安装日志目录 ...

  3. bt种子文件文件结构

      估计80%以上接触互联网的人都知道bt是什么东西,任何一个用bt下载的人都知道这样一个概念,种子.bt种子就是记录了p2p对等网络中tracker, nodes, files等信息,也就是说,这个 ...

  4. House Of Hello恶搞包为什么如此受热捧!

    凤凰时尚    在大多数人的心中,奢侈品都是昂贵的,摆在精美的橱窗中,动辄上万的价格,高贵而冷艳,也让很多人望而却步.然而,最近在很多时尚年轻一族中却流传着这样一句话“昂贵不等于奢侈,奢侈是一种生活态 ...

  5. 大用处--PowerShell Management Library for Hyper-V.

    http://pshyperv.codeplex.com/releases 用脚本来收集及集成HYPER-V管理. 越来越似KVM,LIBVIRT啦.

  6. 电容式触摸控制器PCB布局

    在目前市场上可提供的PCB(印刷电路板)基材中,FR4是最常用的一种.FR4是一种玻璃纤维增强型环氧树脂层压板,PCB可以是单层或多层. 在触摸模块的尺寸受限的情况下,使用单层PCB不是总能行得通的, ...

  7. oracle中的exists 和not exists 用法详解(转)

    有两个简单例子,以说明 “exists”和“in”的效率问题 1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ; ...

  8. Oracle预估的基数算法

    SQL> create table t as select * from dba_objects; Table created. SQL> create index idx_t on t( ...

  9. 数学(线性规划): ZJOI2013 防守战线

    偷懒用的线性规划. #include <iostream> #include <cstring> #include <cstdio> using namespace ...

  10. 后缀数组:HDU1043 Longest Common Substring

    Longest Common Substring Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java ...