解析几何--最小圆覆盖
作者:互联网
最小圆覆盖问题指平面上有n个点,给定n个点的坐标,找到一个半径最小的圆,将n个点全部包围,点可以在圆上。
求最小圆覆盖问题的方法有很多种。一步一步学习。
先介绍增量法的实现步骤。
点增量法
(1)在点集中任取三点A,B,C。
(2)做一个包含A,B,C三点的小圆,圆周可能通过这三点,也可能只通过其中两个点,但包含第三个点。后一种情况,圆周上两点一定位于圆的一条直径的两端。
(3)在点集中找出距离(2)所建圆圆心最远的D点,若D点已在园内||圆周上,则该圆即为所求的圆,算法结束,否则执行(4)
(4)在A,B,C,D中选三个点,使由他们生成的一个包含这四个点的圆最小,这三点成为新的A,B,C,返回(2),若(4)生成的圆的圆周只通过A,B,C,D中的两点,则圆周上的两点取成新的A和B,从另两点中任取一点作为新的C。
三角形增量法
(1)任意选择两点Pi,Pj,然后以Pi,Pj为端点,Pi,Pj的中点为圆心,构造一个圆。如果这个圆包括所有的点,那么他就是最小的圆。中点也就是最小圆的圆心;否则选择圆外一点Pk;
(2)如果Pi,Pj,Pk三点形成的三角形是直角或钝角三角形,那么该直角||钝角三角形所对应的两点为Pi,Pj,然后再次重新构建一个以新Pi,Pj为直径的圆,重复(1)的步骤;否则,这三点形成一个锐角三角形,构造一个外接圆,如果这个圆包含所有的点,结束。否则进入(3)
(3)选择一些不在园内的点Pl,设点Q为{Pi,Pj,Pk}中离Pl最远的点,连接并延长点Pl和Q,将平面分成两个半平面,设顶点R为{Pi,Pj,Pk}中与Pl不在一个半平面中的点,得到Pl,Q,R三点,返回(1)。
Code:以HDU-3007-Buried memory(板子)为例
// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdio.h>
#include<string.h>
#include<math.h>
//#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define Pair pair<int,int>
//#define max(a,b) (a)>(b)?(a):(b)
//#define min(a,b) (a)<(b)?(a):(b)
#define clean(a,b) memset(a,b,sizeof(a))// 水印
//std::ios::sync_with_stdio(false);
// register
const int MAXN=1e3+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
struct Point{
double x,y;
Point(double _x=0,double _y=0){
x=_x;y=_y;
}
friend Point operator + (const Point &a,const Point &b){
return Point(a.x+b.x,a.y+b.y);
}
friend Point operator - (const Point &a,const Point &b){
return Point(a.x-b.x,a.y-b.y);
}
friend double operator ^ (Point a,Point b){
return a.x*b.y-a.y*b.x;
}
}Dots[MAXN],Dots2[MAXN];
struct V{
Point start,end;double ang;
V(Point _start=Point(0,0),Point _end=Point(0,0),double _ang=0.0){
start=_start;end=_end;ang=_ang;
}
friend V operator + (const V &a,const V &b){
return V(a.start+b.start,a.end+b.end);
}
friend V operator - (const V &a,const V &b){
return V(a.start-b.start,a.end-b.end);
}
}Edge[MAXN],Edge2[MAXN],stk[MAXN];
struct Circle{
double r;
Point centre;
Circle(Point _centre=Point(0,0),double _r=0){
centre=_centre;r=_r;
}
}ansC;
struct Triangle{
Point p[3];
};
int n;
int Parellel(const V &x,const V &y){
return fabs((x.end-x.start)^(y.end-y.start))<EPS;
}
Point LineInterDot(const V &l1,const V &l2){
Point p;
double S1=(l2.end-l1.start)^(l2.start-l1.start);
double S2=(l2.start-l1.end)^(l2.end-l1.end);
p.x=(l1.start.x*S2+l1.end.x*S1)/(S1+S2);
p.y=(l1.start.y*S2+l1.end.y*S1)/(S1+S2);
return p;
}
double Distance(Point p1,Point p2){
p2=p2-p1;
return sqrt(p2.x*p2.x+p2.y*p2.y);
}
double TriangleArea(Triangle t){
return fabs((t.p[1]-t.p[0])^(t.p[2]-t.p[0]))/2.0;
}
Circle CircumCircleOfTriangle(const Triangle &t){
Circle tmp;
double a,b,c,c1,c2;
double xa,ya,xb,yb,xc,yc;
a=Distance(t.p[0],t.p[1]);b=Distance(t.p[1],t.p[2]);c=Distance(t.p[2],t.p[0]);
tmp.r=a*b*c/TriangleArea(t)/4.0;
xa=t.p[0].x;ya=t.p[0].y;
xb=t.p[1].x;yb=t.p[1].y;
xc=t.p[2].x;yc=t.p[2].y;
c1=(xa*xa+ya*ya-xb*xb-yb*yb)/2.0;
c2=(xa*xa+ya*ya-xc*xc-yc*yc)/2.0;
tmp.centre.x=(c1*(ya-yc)-c2*(ya-yb))/((xa-xb)*(ya-yc)-(xa-xc)*(ya-yb));
tmp.centre.y=(c1*(xa-xc)-c2*(xa-xb))/((ya-yb)*(xa-xc)-(ya-yc)*(xa-xb));
return tmp;
}
Circle MinCircle2(int u,Triangle t){
if(u==0) return Circle(Point(0,0),-2.0);
else if(u==1) return Circle(t.p[0],0);
else if(u==2) return Circle(Point((t.p[0].x+t.p[1].x)/2.0,(t.p[0].y+t.p[1].y)/2.0),Distance(t.p[0],t.p[1])/2.0);
else if(u==3) return CircumCircleOfTriangle(t);
}
void MinCircle(int n,int u,Triangle t){
ansC=MinCircle2(u,t);
if(u==3) return ;
for(int i=1;i<=n;++i){
if(Distance(Dots[i],ansC.centre)>ansC.r){
t.p[u]=Dots[i];
MinCircle(i-1,u+1,t);
Point temp=Dots[i];
for(int j=i;j>=2;--j){
Dots[j]=Dots[j-1];
}Dots[1]=temp;
}
}
}
int main(){
int n;
while(~scanf("%d",&n)){
if(n==0) break;
for(int i=1;i<=n;++i){
scanf("%lf%lf",&Dots[i].x,&Dots[i].y);
}Triangle t;
MinCircle(n,0,t);
printf("%.2lf %.2lf %.2lf\n",ansC.centre.x,ansC.centre.y,ansC.r);
}
}
/*
*/
标签:Dots,三点,Pi,覆盖,最小,解析几何,Pj,include,Pl 来源: https://blog.csdn.net/qq_40482358/article/details/88026033