题意:给你一个圆心和圆的半径,在给你一个额外的点,然后让你找一个圆,使得该圆能尽可能多的覆盖已知的圆并且不能覆盖已知圆的圆外区域和呢一个额外的点,输出所求圆的圆心和半径
题解:这道题思路很简单,很容易想到的贪心思想是已知圆心和呢一个额外的点构成的直线与圆相交的两点中,和额外的点分别位于已知圆心两侧的呢个交点才是我们要的点,并且该点与已知额外的呢个点构成的直径便是我们所求圆的直径,圆心就是这两个点的中间点,所以本题的难点其实就是求两点构成的直线与圆的交点,因为只有一个交点是我们需要的,并且直线上的两点我们已知了,其中的一些距离也很容易求出来,因此我们可以利用相似三角形定理求出交点坐标,注意要分6种情况讨论。。。思路很明确,记得一定要注意判呢个额外的点假如在已知圆的圆外,呢我们就不用求了,直接输出已知圆的半径和圆心坐标即可(这个地方我wa了一万年)。。。。当然也可以联立方程组直接求解,你开心就好。
#include<math.h>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define ll long long
double R,r,x,y,xx,yy,xxx,yyy;
int main(void)
{
scanf("%lf%lf%lf%lf%lf",&R,&x,&y,&xx,&yy);
double d=sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy));
r=(sqrt((x-xx)*(x-xx)+(y-yy)*(y-yy))+R)/2.0;
if(d>=R)
{
printf("%.10f %.10f %.10f\n",x,y,R);
return 0;
}
if(x==xx)
{
if(y==yy)
printf("%.10f %.10f %.10f\n",x+R/2.0,y,R/2);
else
{
if(y>yy)
printf("%.10f %.10f %.10f\n",x,yy+r,r);
else
printf("%.10f %.10f %.10f\n",x,yy-r,r);
}
}
else
{
if(xx<x)
{
if(yy<y)
{
xxx=2.0*r/d*(x-xx)+xx;
yyy=2.0*r/d*(y-yy)+yy;
xxx=(xxx+xx)/2.0;yyy=(yyy+yy)/2.0;
printf("%.10f %.10f %.10f\n",xxx,yyy,r);
}
else
{
xxx=(2.0*r*x-(2.0*r-d)*xx)/d;
yyy=(2.0*r*y-(2.0*r-d)*yy)/d;
xxx=(xxx+xx)/2.0;yyy=(yyy+yy)/2.0;
printf("%.10f %.10f %.10f\n",xxx,yyy,r);
}
}
else
{
if(yy>=y)
{
xxx=((2.0*r-d)*xx-2.0*r*x)/d;
yyy=((2.0*r-d)*yy-2.0*r*y)/d;
xxx=-xxx;yyy=-yyy;
xxx=(xxx+xx)/2.0;yyy=(yyy+yy)/2.0;
printf("%.10f %.10f %.10f\n",xxx,yyy,r);
}
else
{
xxx=(2.0*r*x-(2.0*r-d)*xx)/d;
yyy=(2.0*r*y-(2.0*r-d)*yy)/d;
xxx=(xxx+xx)/2.0;yyy=(yyy+yy)/2.0;
printf("%.10f %.10f %.10f\n",xxx,yyy,r);
}
}
}
return 0;
}