给定一个点集,求出能覆盖点集内所有点的半径最小的圆。包含点在圆上的情况。个人感觉算是比较麻烦的计算几何模板了。
在网上看了很多解题,大多数都摘抄自《求一个包含点集所有点的最小圆的算法》这篇论文。
论文中提出的算法一共分一下四步:
第 1 步. 在点集中任取 3 点 A , B , C .
第 2 步. 作一个包 含 A , B , C 三点的最小 圆. 圆周可 能通过这 3 点( 如图 1 所示) , 也 可能只通过
其中两点, 但包含第 3 点. 后一种情况圆周上的两点一定是 位于圆的一条直径的两端.
第 3 步. 在点集中找 出距离第 2 步所建圆圆心最远的点 D . 若 D 点已在圆内或圆周上, 则该
圆即为所求的圆, 算法结束. 否则, 执行第 4 步.
第 4 步. 在 A , B , C , D 中 选 3 个点, 使 由它们生成的一个 包含这 4 点的圆为最 小. 这 3 点成
为新的 A , B 和 C , 返回执 行第 2 步 .
若在第 4 步生成的圆的圆周只通过 A , B , C , D 中的两点, 则圆周上的两点取成新的 A 和 B ,
从另两点中任取一点作为新的 C .
但是我读的时候感觉其中最关键的第四步说的最为模糊了。
下面是我自己的一些关于求四边形即四个点的最小圆覆盖的一些想法。
1. 若此四边形中存在大于等于180度的内角时,则可看作求三角形的最小覆盖圆(钝角三角形为以长边做直径的圆,否则为该三角形外接圆)。
2. 若存在两个锐角,两个非锐角,则必为两个锐角顶点连线为直径的圆。
3. 若有三个锐角,一个非锐角,则必为三个锐角顶点组成的三角形的外接圆。
4. 若有四个直角,则任选其中三点组成三角形求其外接圆即可。
解决了第四步,剩下的就是按照上述算法求解了。
下面是AC代码,里面还有一些其他的模板,一直想攒一套完整的模板,所以就没删,求最小点集覆盖圆的函数为 Cal_Min_Circle(P *p,int n)。
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <cmath>
#include <algorithm>
#define LL long long
#define PI (acos(-1.0))
#define EPS (