体验过\(O(n^3)\)过\(10^5\)吗?快来体验一波当\(wys\)的快感吧\(QAQ\)

前置芝士1:二元一次方程组求解

\[\begin{cases}a1 * x + b1*y=c1\\a2 * x + b2*y=c2\end{cases}
\]

(其中\(a1,a2,b1,b2,c1,c2\)为已知量)

由\(②\)式得:

\[x=\frac{c2-b2*y}{a2}
\]

带入\(①\)式并化简得:

\[y=\frac{c1-\frac{a1*c2}{a2}}{b1-\frac{a1*b2}{a2}}
\]

分子分母同时乘以\(a2\)得:

\[y=\frac{a2*c1-a1*c2}{a2*b1-a1*b2}
\]

同理可得(把\(a,b\)互换即可):

\[x=\frac{b2*c1-b1*c2}{b2*a1-b1*a2}
\]

前置芝士2:三点定圆

给出三个点,求出圆心&半径

\[\begin{cases}x1^2-2x1*x0+x0^2+y1^2-2y1*y0+y0^2=r^2\\x2^2-2x2*x0+x0^2+y2^2-2y2*y0+y0^2=r^2\\x3^2-2x3*x0+x0^2+y3^2-2y3*y0+y0^2=r^2\end{cases}
\]

\(②-①\)和\(③-①\),并化简得:

\[\begin{cases}2*(x2-x1)x+2*(y2-y1)y=x2^2-x1^2+y2^2-y1^2\\2*(x3-x1)x+2*(y3-y1)y=x3^2-x1^2+y3^2-y1^2\end{cases}
\]

我们将三点定圆的柿子对应二元一次方程组中,可知:

\[a1=x2-x1,\quad a2=x3-x1
\]

\[b1=y2-y1,\quad b2=y3-y1
\]

\[c1=\frac{x2^2-x1^2+y2^2-y1^2}{2},\quad c2=\frac{x3^2-x1^2+y3^2-y1^2}{2}
\]

然后就可以根据三个点求出圆心和半径了

正文

跟据前置芝士,我们知道对于任意三个不共线的点,我们可以求出三点定的圆,所以一个明显的想法就是枚举三个点

我们先枚举第一个点,有两种情况

①:当前点在当前外面,即\(dis(\)圆心,该点\()>r\)那么我们不管这个点

②:不是情况①的情况,那么我们就需要重新构造这个圆来包含所有的点了

怎么构造呢?我们重新枚举两外两个已经遍历过的点,组成三个点。同理,若重新构造的圆包括了三个点,那么就不管,若有任意一个在圆外,那么我们根据前置芝士重新确定圆心和半径即可

PS:本题出题人过于duliu,故意构造数据卡掉了上述解法,所以我们需要一个神奇的东西:随\((da)\)机\((luan)\)增\((shu)\)量\((ju)\)法,来防止掉精度

代码如下:

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. #define il inline
  4. #define re register
  5. #define D double
  6. il int read()
  7. {
  8. re int x = 0, f = 1; re char c = getchar();
  9. while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar();}
  10. while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
  11. return x * f;
  12. }
  13. #define rep(i, s, t) for(re int i = s; i <= t; ++ i)
  14. #define eps 1e-12
  15. #define maxn 100005
  16. #define ff(x) (x) * (x)
  17. int n, m;
  18. D r;
  19. struct node
  20. {
  21. D x, y;
  22. }o, e[maxn];
  23. il D dis(node a, node b){return sqrt(ff(a.x - b.x) + ff(a.y - b.y));}
  24. il void get(node a, node b, node c)
  25. {
  26. D a1 = b.x - a.x, a2 = c.x - a.x, b1 = b.y - a.y, b2 = c.y - a.y;
  27. D c1 = (ff(b.x) - ff(a.x) + ff(b.y) - ff(a.y));
  28. D c2 = (ff(c.x) - ff(a.x) + ff(c.y) - ff(a.y));
  29. o = (node){(b2 * c1 - b1 * c2) / (b2 * a1 * 2 - b1 * a2 * 2),
  30. (a2 * c1 - a1 * c2) / (a2 * b1 * 2 - a1 * b2 * 2)};
  31. r = dis(a, o);
  32. }
  33. il void work()
  34. {
  35. o = e[1], r = 0;
  36. rep(i, 2, n)
  37. {
  38. if(dis(o, e[i]) > r + eps)
  39. {
  40. o = e[i], r = 0;
  41. rep(j, 1, i - 1)
  42. {
  43. if(dis(o, e[j]) > r + eps)
  44. {
  45. o.x = (e[i].x + e[j].x) / 2, o.y = (e[i].y + e[j].y) / 2;
  46. r = dis(o, e[j]);
  47. rep(k, 1, j - 1) if(dis(o, e[k]) > r + eps) get(e[i], e[j], e[k]);
  48. }
  49. }
  50. }
  51. // printf("%.10lf\n%.10lf %.10lf\n", r, o.x, o.y);
  52. }
  53. }
  54. int main()
  55. n = read();
  56. rep(i, 1, n) scanf("%lf%lf", &e[i].x, &e[i].y);
  57. random_shuffle(e + 1, e + n + 1);
  58. work();
  59. printf("%.10lf\n%.10lf %.10lf", r, o.x, o.y);
  60. return 0;
  61. }

P1742 最小圆覆盖(计算几何)的更多相关文章

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

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

  2. 洛谷 P1742 最小圆覆盖 (随机增量)

    题目链接:P1742 最小圆覆盖 题意 给出 N 个点,求最小的包含所有点的圆. 思路 随机增量 最小圆覆盖一般有两种做法:随机增量和模拟退火.随机增量的精确度更高,这里介绍随机增量的做法. 先将所有 ...

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

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

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

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

  5. P1742 最小圆覆盖

    \(\color{#0066ff}{题目描述}\) 给出N个点,让你画一个最小的包含所有点的圆. \(\color{#0066ff}{输入格式}\) 先给出点的个数N,2<=N<=1000 ...

  6. HDU 3007 最小圆覆盖 计算几何

    思路: 随机增量法 (好吧这数据范围并不用) //By SiriusRen #include <cmath> #include <cstdio> #include <al ...

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

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

  8. 2018.10.15 bzoj3564: [SHOI2014]信号增幅仪(坐标处理+最小圆覆盖)

    传送门 省选考最小圆覆盖? 亦可赛艇(你们什么都没看见) 在大佬的引领下成功做了出来. 就是旋转坐标使椭圆的横轴跟xxx轴平行. 然后压缩横坐标使得其变成一个圆. 然后跑最小覆盖圆就可以了. 注意题目 ...

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

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

随机推荐

  1. 伙伴系统之避免碎片--Linux内存管理(十六)

    1 前景提要 1.1 碎片化问题 分页与分段 页是信息的物理单位, 分页是为了实现非连续分配, 以便解决内存碎片问题, 或者说分页是由于系统管理的需要. 段是信息的逻辑单位,它含有一组意义相对完整的信 ...

  2. CentOS7中利用Xshell6向虚拟机本地上传文件

    环境交代 Linux系统:CentOS7, Xshell版本:6 操作步骤 下面我们以一个文件上传来演示用法 第一步 建立连接,这里不多说 在Xshell中点击如下图标,或者直接按 Alt+Ctrl+ ...

  3. Go语言学习笔记-流程控制(二)

    Go语言流程控制 字典类型Map 1.上节遗留:map字典类型 变量声明:var myMap map[string] PersonInfo 其中,myMap是变量名,string是键的类型,Perso ...

  4. Kafka 安装配置 windows 下

    Kafka 安装配置 windows 下 标签(空格分隔): Kafka Kafka 内核部分需要安装jdk, zookeeper. 安装JDK 安装JDK就不需要讲解了,安装完配置下JAVA_HOM ...

  5. 【PAT】A1002 A+B for Polynomials

    仅有两个要注意的点: 如果系数为0,则不输出,所以输入结束以后要先遍历确定系数不为零的项的个数 题目最后一句,精确到小数点后一位,如果这里忽略了,会导致样例1,3,4,5都不能通过

  6. linux vi粘贴格式易错乱

    对于一些冗长的代码完全可以粘贴的时候,vi粘贴所有格式全部错乱,完全无法阅读. 解决办法:esc进入命令行模式后,输入 :set paste,然后再i进入粘贴编辑模式,即可正常复制并保留原有格式-

  7. jsplumb 中文基础教程

    jsplumb 中文基础教程 https://github.com/wangduanduan/jsplumb-chinese-tutorial

  8. JavaScript 面向对象之原型对象

    原型的概述 我们创建的每个函数都有一个 prototype(原型)属性,这个属性是一个对象,它的用途是包含可以由特定类型的所有实例共享的属性和方法. 逻辑上可以这么理解:prototype 通过调用构 ...

  9. 基于SpringMVC拦截器和注解实现controller中访问权限控制

    SpringMVC的拦截器HandlerInterceptorAdapter对应提供了三个preHandle,postHandle,afterCompletion方法. preHandle在业务处理器 ...

  10. java将对象转map,map转对象工具类

    /** * 将map转换为一个对象 * * @param map * @param beanClass * @return * @throws Exception */ public static O ...