最小圆覆盖问题指平面上有n个点,给定n个点的坐标,找到一个半径最小的圆,将n个点全部包围,点可以在圆上。
求最小圆覆盖问题的方法有很多种。一步一步学习。
先介绍增量法的实现步骤。
目录
HDU-3007-Buried memory(最小圆覆盖板子)
BZOJ-1336: [Balkan2002]Alien最小圆覆盖
点增量法
(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);
}
/*
*/