2019西北工业大学程序设计创新实践基地春季选拔赛(重现赛) A Chino with Geometry

链接:https://ac.nowcoder.com/acm/contest/553/A
 

题目描述

Chino的数学很差,因此Cocoa非常担心。这一天,Cocoa准备教Chino学习圆与直线的位置关系。
众所周知,直线和圆有三种位置关系:相离、相切、相割,主要根据圆心到直线的距离来判定。

现在我们来看看作业吧:

是以整点为圆心、正整数为半径的圆,整点分别是圆外一点以及轴上的一点,形成一条圆的割线(也就是和圆有两个交点)。现在Cocoa想要知道,的值是多少?
题目对于Chino来说太难啦,你能帮一帮Chino吗?

输入描述:

六个正整数x0, y0, r, x1, y1, y2

输出描述:

题目要求的答案,精确到整数

示例1

输入

复制

2 2 1 3 1 2

输出

复制

1

思路:

一开始想的是求出直线与圆的交点的两个坐标,然后直接算出|BD|和|BE|的长度。

这样做需要求出直线和圆的方程然后联立解二元一次方程。

这里参考的另一个博主的给出的方法求得。

链接如下:

求圆和直线相交的两个交点的坐标

代码如下:

#include <bits/stdc++.h>
using namespace std;
double x00,y00,r,x11,y11,x22,y22;
double k,b;
double x33,y33,x44,y44;
double aa,bb,cc;
double re;
double ans;
//求y=kx+b中的k和b
void solkb()
{
    b=y22;
    k=(y11-y22)/x11;
}
//求圆和直线联立的ax+by+c=0中的a,b,c
void solabc()
{
    aa=1+k*k;
    bb=2*k*(b-y00)-2*x00;
    cc=x00*x00+(b-y00)*(b-y00)-r*r;
}
//解二元一次方程
void solxy34()
{
    re=bb*bb-4*aa*cc;
    x33=(-bb+sqrt(re))/(2*aa);
    x44=(-bb-sqrt(re))/(2*aa);
    y33=k*x33+b;
    y44=k*x44+b;
}
//根据坐标系求距离
void solve()
{
    double a1=fabs(y33-y11);
    double b1=fabs(x11-x33);
    double r1=sqrt(a1*a1+b1*b1);
    double a2=fabs(y44-y11);
    double b2=fabs(x11-x44);
    double r2=sqrt(a2*a2+b2*b2);
    ans=r1*r2;
}
int main()
{
    x22=0;
    scanf("%lf%lf%lf%lf%lf%lf",&x00,&y00,&r,&x11,&y11,&y22);
    solkb();
    solabc();
    solxy34();
    solve();
    printf("%.0lf\n",ans);
    return 0;
}

通过看排名大佬提交的代码,发现还有一种更简便的方法:

直接用B到O的距离的平方减去半径的平方就是答案。。。感觉我高中的时候应该知道为什么。。

参考代码如下:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
    int x0,y0,r,x1,y1,y2;
    while(EOF!=scanf("%d%d%d%d%d%d",&x0,&y0,&r,&x1,&y1,&y2)){
        ll a=1ll*(x1-x0)*(x1-x0)+1ll*(y1-y0)*(y1-y0);
        double ans=a-1ll*r*r;
        printf("%.0lf\n",ans);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_41410799/article/details/89069607