解析几何--最小圆覆盖

最小圆覆盖问题指平面上有n个点,给定n个点的坐标,找到一个半径最小的圆,将n个点全部包围,点可以在圆上。

求最小圆覆盖问题的方法有很多种。一步一步学习。

先介绍增量法的实现步骤。

目录

点增量法

三角形增量法

HDU-3007-Buried memory(最小圆覆盖板子)

BZOJ-1336: [Balkan2002]Alien最小圆覆盖

BZOJ-1337: 最小圆覆盖

BZOJ-2823: [AHOI2012]信号塔

洛谷-P1742 最小圆覆盖

洛谷-P2533 [AHOI2012]信号塔


点增量法

(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)。

有一道例题,可直接作为板子来用:

HDU-3007-Buried memory(最小圆覆盖板子)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3007

题目大意:给出n个点,找出一个最小的圆,使得这个圆能够覆盖所有的点。

思路:板子。

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);
	}
}
/*

*/

有关题目:

BZOJ-1336: [Balkan2002]Alien最小圆覆盖

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1336

思路:板子

ACCode:

// 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=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double PI=acos(-1.0);
const double EPS=1.0e-10;

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];
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);
	}
};
struct Circle{
	double r;
	Point centre;
	Circle(Point _centre=Point(0,0),double _r=0){
		centre=_centre;r=_r;
	}
}AnsCir;
struct Triangle{
	Point p[3];
};

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);
	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){
	AnsCir=MinCircle2(u,t);
	if(u==3) return ;
	for(int i=1;i<=n;++i){
		if(Distance(Dots[i],AnsCir.centre)>AnsCir.r+EPS){
			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;scanf("%d",&n);
	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",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
	printf("%.10lf\n%.10lf %.10lf\n",AnsCir.r,AnsCir.centre.x,AnsCir.centre.y);
}
/*

*/

BZOJ-1337: 最小圆覆盖

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=1337

思路:板子

ACCode:

// 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=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double PI=acos(-1.0);
const double EPS=1.0e-10;

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];
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);
	}
};
struct Circle{
	double r;
	Point centre;
	Circle(Point _centre=Point(0,0),double _r=0){
		centre=_centre;r=_r;
	}
}AnsCir;
struct Triangle{
	Point p[3];
};

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);
	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){
	AnsCir=MinCircle2(u,t);
	if(u==3) return ;
	for(int i=1;i<=n;++i){
		if(Distance(Dots[i],AnsCir.centre)>AnsCir.r+EPS){
			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;scanf("%d",&n);
	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",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
	printf("%.3lf\n",AnsCir.r);
}
/*

*/

BZOJ-2823: [AHOI2012]信号塔

题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=2823

思路:板子(莫非这就是一个板子走天下??)精度也没说1A真是幸运啊。

ACCode:

// 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=1e6+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double PI=acos(-1.0);
const double EPS=1.0e-10;

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];
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);
	}
};
struct Circle{
	double r;
	Point centre;
	Circle(Point _centre=Point(0,0),double _r=0){
		centre=_centre;r=_r;
	}
}AnsCir;
struct Triangle{
	Point p[3];
};

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);
	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){
	AnsCir=MinCircle2(u,t);
	if(u==3) return ;
	for(int i=1;i<=n;++i){
		if(Distance(Dots[i],AnsCir.centre)>AnsCir.r+EPS){
			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;scanf("%d",&n);
	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",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
	printf("%.2lf %.2lf %.2lf\n",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
}
/*

*/

洛谷-P1742 最小圆覆盖

题目链接:https://www.luogu.org/problemnew/show/P1742

题目大意:最小圆覆盖板子。

思路:板子,其实这道题需要对输入的数据进行重新打乱,要不然可能会被卡??具体原因应该是算法的问题把。正在想怎么解决这个问题。。。

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdlib.h>
#include<string.h> 
#include<stdio.h>
#include<math.h> 
#include<time.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=1e6+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double EPS=1.0e-12;
const double PI=acos(-1.0);

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];
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);
    }
};
struct Circle{
    double r;
    Point centre;
    Circle(Point _centre=Point(0,0),double _r=0){
        centre=_centre;r=_r;
    }
}AnsCir;
struct Triangle{
    Point p[3];
};

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);
    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){
    AnsCir=MinCircle2(u,t);
    if(u==3) return ;
    for(int i=1;i<=n;++i){
        if(Distance(Dots[i],AnsCir.centre)>AnsCir.r+EPS){
            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;
        }
    }
}
void intt(int n){
	for(int i=1;i<=n;++i){
		int j=rand()*MAXN%(n+1);
		if(j<1) j=1;//cout<<i<<" "<<j<<endl;
		swap(Dots[i],Dots[j]);
	}
}
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%lf%lf",&Dots[i].x,&Dots[i].y);
    }Triangle t;
    intt(n);
    MinCircle(n,0,t);
    //printf("%.2lf %.2lf %.2lf\n",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
    printf("%.10lf\n%.10lf %.10lf\n",AnsCir.r,AnsCir.centre.x,AnsCir.centre.y);
}
/*

*/

洛谷-P2533 [AHOI2012]信号塔

题目链接:https://www.luogu.org/problemnew/show/P2533

题目大意:上面信号塔的原题基本上。

思路:板子,加个随机数据

ACCode:

// luogu-judger-enable-o2
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<stdlib.h>
#include<string.h> 
#include<stdio.h>
#include<math.h> 
#include<time.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=1e6+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const int MOD=998244353;
const double EPS=1.0e-12;
const double PI=acos(-1.0);

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];
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);
    }
};
struct Circle{
    double r;
    Point centre;
    Circle(Point _centre=Point(0,0),double _r=0){
        centre=_centre;r=_r;
    }
}AnsCir;
struct Triangle{
    Point p[3];
};

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);
    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){
    AnsCir=MinCircle2(u,t);
    if(u==3) return ;
    for(int i=1;i<=n;++i){
        if(Distance(Dots[i],AnsCir.centre)>AnsCir.r+EPS){
            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;
        }
    }
}
void intt(int n){
	for(int i=1;i<=n;++i){
		int j=rand()*MAXN%(n+1);
		if(j<1) j=1;//cout<<i<<" "<<j<<endl;
		swap(Dots[i],Dots[j]);
	}
}
int main(){
    int n;scanf("%d",&n);
    for(int i=1;i<=n;++i){
        scanf("%lf%lf",&Dots[i].x,&Dots[i].y);
    }Triangle t;
    intt(n);
    MinCircle(n,0,t);
    //printf("%.2lf %.2lf %.2lf\n",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
    printf("%.2lf %.2lf %.2lf\n",AnsCir.centre.x,AnsCir.centre.y,AnsCir.r);
}
/*

*/

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/88026033
今日推荐