题目链接: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. apm 应用性能管理(启动优化/ 掉帧卡顿/ 耗电/ 内存泄漏等)

    APM 首先查看各个阶段耗时 : (环境变量设置 dyldPRINTSTATISTICS = 1选项,) 1. 启动优化 关键: 找到耗时的原因 t总 = t1 (premain) + t1(main ...

  2. 同时连接gitlab和github

    ---恢复内容开始--- 原文地址:https://juejin.im/post/5ac0cf356fb9a028df22c246 1. 分别生成gitlab和github的ssh key 生成第一个 ...

  3. OSX 创建 randisk(或称 tmpfs)

    创建步骤: #!/bin/bash ramdisk_size_in_mb= mount_point=/private/tmp ramdisk_size_in_sectors=$((${ramdisk_ ...

  4. Cocos2d Box2D之静态刚体

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. b2_staticBody 在模拟环境下静态物体是不会移动的,就好像有无限大的质量.在Box2D的内部会将质量至反,存储为零.静态物体也可 ...

  5. Mybatis的分支选择和In循环

    Mybatis的分支选择: <choose> <when test="patientNo != null and patientNo != ''"> and ...

  6. System.Net.Mail.SmtpException:不允许使用邮箱名称.

    使用SmtpClient发送邮件的时候,出现了如题错误. 解决方案: 将  SmtpClient.UseDefaultCredentials  属性设置为 true . 官方文档说明: Some SM ...

  7. js运算符的优先级的顺序列表

    优先级权重 运算符 17 ..[].new 16 () 15 ++.-- 14 !.~.+(单目).-(单目).typeof.void.delete 13 %.*./ 12 +(双目).-(双目) 1 ...

  8. java web中的get和post(笔记)

    W3CSchool 在客户机和服务器之间进行请求-响应时,两种最常被用到的方法是:GET 和 POST. GET - 从指定的资源请求数据. POST - 向指定的资源提交要被处理的数据 GET 方法 ...

  9. 力扣 — Rotate List()

    题目描述: 中文: 给定一个链表,旋转链表,将链表每个节点向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: 1->2->3->4->5->NULL, k = ...

  10. python bezier 曲线

    1.手写bezier公式,生成bezier代码, 如果给的点数过多,则会生成一半bezier曲线,剩下的一半就需要进行拼接: import numpy as np import matplotlib. ...