题意:给你n个圆,求包含在所有圆的区域内距离原点最远的点。
题解:这个点必定是交点或者是圆心与原点的直线与圆的交点。
AC代码:
#include<stdio.h>
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define eps 1e-8
using namespace std;
struct point
{
double x,y;
point(){}
point(double x,double y)
{
this->x=x;
this->y=y;
}
};
double max(double a,double b){return a>b?a:b;}
double min(double a,double b){return a<b?a:b;}
point intersection(point u1,point u2,point v1,point v2)
{
point ret=u1;
double t=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
return ret;
}
double distance(point p1,point p2)
{
return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
void intersection_line_circle(point c,double r,point l1,point l2,point& p1,point& p2)
{
point p=c;
double t;
p.x+=l1.y-l2.y;
p.y+=l2.x-l1.x;
p=intersection(p,c,l1,l2);
t=sqrt(r*r-distance(p,c)*distance(p,c))/distance(l1,l2);
p1.x=p.x+(l2.x-l1.x)*t;
p1.y=p.y+(l2.y-l1.y)*t;
p2.x=p.x-(l2.x-l1.x)*t;
p2.y=p.y-(l2.y-l1.y)*t;
}
void intersection_circle_circle(point c1,double r1,point c2,double r2,point& p1,point& p2)
{
point u,v;
double t;
t=(1+(r1*r1-r2*r2)/distance(c1,c2)/distance(c1,c2))/2;
u.x=c1.x+(c2.x-c1.x)*t;
u.y=c1.y+(c2.y-c1.y)*t;
v.x=u.x+c1.y-c2.y;
v.y=u.y-c1.x+c2.x;
intersection_line_circle(c1,r1,u,v,p1,p2);
}
struct circle
{
double r;
point p;
}cir[55];
int mark[55],n;
bool judge(point p)
{
for(int i=0;i<n;i++)
{
double dist=distance(cir[i].p,p);
if(dist<cir[i].r+eps)continue;
else return false;
}
return true;
}
int main()
{
scanf("%d",&n);
for(int i=0;i<n;i++)
scanf("%lf%lf%lf",&cir[i].p.x,&cir[i].p.y,&cir[i].r);
int sum=0;
for(int i=0;i<n;i++)
for(int j=i+1;j<n;j++)
{
double dist=distance(cir[i].p,cir[j].p);
if(dist+min(cir[i].r,cir[j].r)<max(cir[i].r,cir[j].r)+eps)
{
if(cir[i].r>cir[j].r)mark[i]=1;
else mark[j]=1;
}
}
for(int i=0;i<n;i++)sum+=mark[i];
if(sum==n-1)
{
for(int i=0;i<n;i++)
{
if(mark[i]==0)
printf("%.3lf\n",distance(point(0.0,0.0),cir[i].p)+cir[i].r);
}
return 0;
}
double ans=0;
for(int i=0;i<n;i++)
{
point p1,p2;
for(int j=0;j<n;j++)
{
if(i==j||mark[i]||mark[j])continue;
intersection_circle_circle(cir[i].p,cir[i].r,cir[j].p,cir[j].r,p1,p2);
if(judge(p1)) ans=max(ans,distance(p1,point(0,0)));
if(judge(p2)) ans=max(ans,distance(p2,point(0,0)));
}
intersection_line_circle(cir[i].p,cir[i].r,point(-cir[i].p.x,-cir[i].p.y),point(2000.0,2000.0*(cir[i].p.y/cir[i].p.x)),p1,p2);
if(judge(p1)) ans=max(ans,distance(p1,point(0,0)));
if(judge(p2)) ans=max(ans,distance(p2,point(0,0)));
}
printf("%.3f\n",ans);
}