题目链接:P1742 最小圆覆盖

题意

给出 N 个点,求最小的包含所有点的圆。

思路

随机增量

最小圆覆盖一般有两种做法:随机增量和模拟退火。随机增量的精确度更高,这里介绍随机增量的做法。

先将所有点随机打乱。

令前 \(i - 1\) 个点的最小覆盖圆为圆 \(O\),加入第 \(i\) 个点。

如果第 \(i\) 个点在圆 \(O\) 内或圆 \(O\) 上,则前 \(i\) 个点的最小覆盖圆还是圆 \(O\)。

否则新得到的最小覆盖圆肯定经过第 \(i\) 个点。然后确定前 \(i − 1\) 个点中还有哪两个点在最小覆盖圆上。

以第 \(i\) 个点为圆心,半径为 \(0\),重复以上过程依次加入点 \(P_j\)。(圆心为 \(\frac{P_i+P_j}{2}\),半径为 \(\frac{|P_iP_j|}{2}\))

固定两个点之后再重复以上步骤找第三个点。(因为需要三个点来确定一个圆)

遍历完所有点之后,所得到的圆就是最小覆盖圆。

时间复杂度为 \(O(n)\)

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;
const db eps = 1e-8;
const db pi = acos(-1.0);
const ll maxn = 1e5 + 10; inline int dcmp(db x) {
if(fabs(x) < eps) return 0;
return x > 0? 1: -1;
} class Point {
public:
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) {}
void input() {
scanf("%lf%lf", &x, &y);
}
bool operator<(const Point &a) const {
return (!dcmp(x - a.x))? dcmp(y - a.y) < 0: x < a.x;
}
bool operator==(const Point &a) const {
return dcmp(x - a.x) == 0 && dcmp(y - a.y) == 0;
}
db dis2(const Point a) {
return pow(x - a.x, 2) + pow(y - a.y, 2);
}
db dis(const Point a) {
return sqrt(dis2(a));
} db dis2() {
return x * x + y * y;
}
db dis() {
return sqrt(dis2());
}
Point operator+(const Point a) {
return Point(x + a.x, y + a.y);
}
Point operator-(const Point a) {
return Point(x - a.x, y - a.y);
}
Point operator*(double p) {
return Point(x * p, y * p);
}
Point operator/(double p) {
return Point(x / p, y / p);
}
db dot(const Point a) {
return x * a.x + y * a.y;
}
db cross(const Point a) {
return x * a.y - y * a.x;
}
db ang(Point a) {
return acos((a.dis() * dis()) / dot(a));
}
};
typedef Point Vector; class Circle {
public:
Point o;
db r;
Circle() {}
Circle(Point o, db r):o(o), r(r){}
// 三点定圆
Circle(Point A, Point B, Point C) {
double a1 = B.x - A.x, b1 = B.y - A.y, c1 = (a1 * a1 + b1 * b1) / 2;
double a2 = C.x - A.x, b2 = C.y - A.y, c2 = (a2 * a2 + b2 * b2) / 2;
double d = a1 * b2 - a2 * b1;
o.x = A.x + (c1 * b2 - c2 * b1) / d;
o.y = A.y + (a1 * c2 - a2 * c1) / d;
r = o.dis(A);
}
Point point(db a) {
return Point(o.x + cos(a) * r, o.y + sin(a) * r);
}
// 点在圆内
bool PinC(Point p) {
db d = p.dis(o);
return dcmp(d - r) < 0;
}
// 点在圆外
bool PoutC(Point p) {
db d = p.dis(o);
return dcmp(d - r) > 0;
}
}; vector<Point> p; // 最小圆覆盖
Circle min_circle(vector<Point> p) {
int sz = p.size();
random_shuffle(p.begin(), p.end());
Circle ans(p[0], 0.0);
for(int i = 0; i < sz; ++i) {
if(ans.PoutC(p[i])) {
ans = Circle(p[i], 0);
for(int j = 0; j < i; ++j) {
if(ans.PoutC(p[j])) {
ans = Circle((p[i] + p[j]) / 2.0, p[i].dis(p[j]) / 2.0);
for(int k = 0; k < j; ++k) {
if(ans.PoutC(p[k])) {
ans = Circle(p[i], p[j], p[k]);
}
}
}
}
}
}
return ans;
} int main() {
int n;
scanf("%d", &n);
for(int i = 0; i < n; ++i) {
Point tmp;
tmp.input();
p.push_back(tmp);
}
Circle ans = min_circle(p);
printf("%.10lf\n%.10lf %.10lf\n", ans.r, ans.o.x, ans.o.y);
return 0;
}

参考

洛谷 P1742 最小圆覆盖 (随机增量)的更多相关文章

  1. (bzoj1337 || 洛谷P1742 最小圆覆盖 )|| (bzoj2823 || 洛谷P2533 [AHOI2012]信号塔)

    bzoj1337 洛谷P1742 用随机增量法.讲解:https://blog.csdn.net/jokerwyt/article/details/79221345 设点集A的最小覆盖圆为g(A) 可 ...

  2. 洛谷P1742 最小圆覆盖(计算几何)

    题面 传送门 题解 之前只是在抄题解--这篇才算是真正自己想的吧-- 首先我们把输入序列给\(random\)一下防止出题人好心送你一个毒瘤序列 我们设\(r\)为当前最大半径,\(o\)为此时对应圆 ...

  3. 洛谷P1742 最小圆覆盖(计算几何)

    题意 题目链接 Sol 暴力做法是\(O(n^3)\)枚举三个点然后check一下是否能包含所有点 考虑一种随机算法,首先把序列random_shuffle一下. 然后我们枚举一个点\(i\),并维护 ...

  4. BZOJ.2823.[AHOI2012]信号塔(最小圆覆盖 随机增量法)

    BZOJ 洛谷 一个经典的随机增量法,具体可以看这里,只记一下大体流程. 一个定理:如果一个点\(p\)不在点集\(S\)的最小覆盖圆内,那么它一定在\(S\bigcup p\)的最小覆盖圆上. 所以 ...

  5. 【bzoj1336/1337/2823】[Balkan2002]Alien最小圆覆盖 随机增量法

    题目描述 给出N个点,让你画一个最小的包含所有点的圆. 输入 先给出点的个数N,2<=N<=100000,再给出坐标Xi,Yi.(-10000.0<=xi,yi<=10000. ...

  6. 【BZOJ1336】[Balkan2002]Alien最小圆覆盖 随机增量法

    [BZOJ1336][Balkan2002]Alien最小圆覆盖 Description 给出N个点,让你画一个最小的包含所有点的圆. Input 先给出点的个数N,2<=N<=10000 ...

  7. [BZOJ2823][BZOJ1336][BZOJ1337]最小圆覆盖(随机增量法)

    算法介绍网上有很多,不解释了. 给出三点坐标求圆心方法:https://blog.csdn.net/liyuanbhu/article/details/52891868 记得先random_shuff ...

  8. hdu 3007【最小圆覆盖-随机增量法模板】

    #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> usin ...

  9. 最小圆覆盖(洛谷 P1742 增量法)

    题意:给定N个点,求最小圆覆盖的圆心喝半径.保留10位小数点. N<1e5: 思路:因为精度要求较高,而且N比较大,所以三分套三分的复杂度耶比较高,而且容易出错. 然是写下增量法吧. 伪代码加深 ...

随机推荐

  1. 测开之路四十三:ajax请求

    ajax固定套路 function http(url, data, method, success, fail) { data = method == 'GET' ? data : JSON.stri ...

  2. iview+vue 使用中遇到的问题(表格、select、radio)

    1.iview+vue中,对表头的动态设置: iview表头若是需要动态设置,可以有两个方法,第一种: children: [ { title: '2017年', align: 'center', k ...

  3. kubernetes安装部署

    1.根据系统内核情况,选择对应的ali云上的镜像,作为仓库的路径指向来配置k8s https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes- ...

  4. ASP.NET开发知识总结

    1.统一异常处理 某商城采用的异常处理方式,是全局统一捕捉,统一处理 思路: 一.定义异常过滤器    实现 MyExceptionFilter : FilterAttribute,IExceptio ...

  5. Python笔记(七)_全局变量与局部变量

    全局变量与局部变量:在函数外部或内部定义的变量 1. 函数内部的变量名首次出现,且在=号左边 不管这个变量在全局域中有没有定义该变量名,都被视为一个局部变量 例1: >>>num=1 ...

  6. 【Python—待解惑的问题】

    疑问1: map()函数第一个参数接收函数,所以 dict.keys() 是函数?这个不是方法吗? map(dict.keys,s) s1.keys() == dict.keys(s1) 输入: Tr ...

  7. 厉害了,Java EE 再次更名为 Jakarta EE

    来自:开源中国 https://www.oschina.net/news/108108/java-ee-rename-as-jakarta-ee Eclipse基金会最近对 Java EE 标准的每个 ...

  8. SQLAlchemy应用到Flask中

    安装模块 pip install Flask-SQLAlchemy 加入Flask-SQLAlchemy第三方组件 from flask import Flask # 导入Flask-SQLAlche ...

  9. 附: K8S入门系列之集群健康检查

    Kubernetes的kubectl常用命令 1. pod操作 # 获取所有的pod kubectl get pods --all-namespaces -o wide # 使用yaml文件创建pod ...

  10. MVC http://stackoverflow.com/tags/model-view-controller/info

    About model-view-controller Model–View–Controller (MVC) is an architectural pattern used in software ...