AcWing 4499. 画圆「掘金日新计划 · 2 月更文挑战」

119 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 6 天,点击查看活动详情

AcWing 4499. 画圆

在一个二维平面内,给定一个以 (x1,y1) 为圆心,半径为 R 的圆以及一个坐标为 (x2,y2) 的点。

请你在二维平面上画一个圆,要求:

  1. 平面中不存在点满足既在你画的圆上,又在给定的圆外。
  2. 给定的点不能在你画的圆内(可以在圆上)。
  3. 被给定圆覆盖且不被你画的圆覆盖的区域面积应尽可能小。

请输出你画的圆的圆心坐标以及半径。

输入格式

共一行,包含 5 个整数 R,x1,y1,x2,y2。

输出格式

三个实数 xans,yans,r,其中 (xans,yans) 是你画的圆的圆心坐标,r 是你画的圆的半径。

答案不唯一时,输出任意合理答案均可。

结果保留六位小数。

数据范围

所有测试点满足 1≤R≤105,|x1|,|y1|,|x2|,|y2|≤105。

输入样例1:

5 3 3 1 1

输出样例1:

3.767767 3.767767 3.914214

输入样例2:

10 5 5 5 15

输出样例2:

5.000000 5.000000 10.000000

思路

这个题其实偏几何,虽然说是acw周赛的第三题,但是其实想明白了就很简单。分析题目就可以知道如果那个点在圆外,是肯定无法满足题意的,所以这个点只能在圆内或者刚好在圆上。不管这个点在圆内还是圆上,都需要用到两点之间的距离公式,这个当然很简单啦,最后比较一下两个情况哪个更短,按题目要求输出就好啦。总的来说,就是分情况加上一点点几何知识就欧克啦。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long

double cal(int x,int y,int xx,int yy){
    int ds=abs(x-xx);
    int dy=abs(y-yy);
    if(!ds&&!dy)return 0.0;
    return (double)sqrt((double)(ds*ds+dy*dy));
}
signed main(){
    int r,x,y,xx,yy;
    cin>>r>>x>>y>>xx>>yy;
    // cout<<r<<" "<<x<<" "<<y<<" "<<xx<<" "<<yy<<endl;
    if(cal(x,y,xx,yy)>=(double)r){
        printf("%.6lf %.6lf %.6lf\n",(double)(x),(double)(y),(double)(r));
        return 0;
    }
    if(x==xx&&y==yy){
        double ansr=r;
        double dx1=x+r;
        double dy1=y;
        printf("%.6lf %.6lf %.6lf\n",(double)((double)xx+dx1)/2,(double)((double)yy+dy1)/2,(double)ansr/2);
    }
    else{
        double ansr=cal(x,y,xx,yy)+r;
        double k=(double)(ansr/cal(x,y,xx,yy));
        double dy=k*(abs(y-yy));
        double dx=k*(abs(x-xx));
        double dx1=0,dy1=0;
        if(xx>=x&&yy>=y){
            dx1=(xx-dx);
            dy1=yy-dy;
        }
        else if(xx<=x&&yy>=y){
            dx1=(xx+dx);
            dy1=yy-dy;
        }
        else if(xx>=x&&yy<=y){
            dx1=(xx-dx);
            dy1=yy+dy;
        }
        else if(xx<=x&&yy<=y){
            dx1=(xx+dx);
            dy1=yy+dy;
        }
        printf("%.6lf %.6lf %.6lf\n",(double)(xx+dx1)/2,(double)(yy+dy1)/2,(double)ansr/2);
    }
    return 0;
}