2019西安邀请赛 Angel‘s Journey 计算几何 计蒜客39270

一道十分简单的计算几何题
这么简单的数学题放在高中可能都不屑于看吧,忘记了,我是个大学生了,hhhh, 怪不得写的这么吃力,希望数学老师不要揍我
To see the problem cilck here
前两天刚刚看了一大堆计算几何的板子呵;看见这题忍不住就开始一顿猛打,真是恨不得把我见过的所有板子都灵活运用一遍,xswl。
不过还是得不厚道的夸自己这化简为繁是为了早日融会贯通,hh。
先上大佬的代码


#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1);
double dis(int x1, int y1, int x2, int y2)
{
    return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
int main()
{
    int T; scanf("%d",&T);
    int rx, ry, r, x, y;
    double ans, p, k, c, s, e, v;
    while(T--)
    {
        scanf("%d%d%d%d%d",&rx, &ry, &r, &x, &y);
        if(abs(x - rx) >= r)
        {
            if(x > rx) ans = dis(rx + r, ry, x, y);
            else ans = dis(rx - r, ry, x, y);
            ans += pi * 2 * r / 4;
        }
        else
        {
            p = dis(rx, ry, x, y);
            ans = sqrt(p * p - r * r);
            c = r / p;
            s = acos(c) * 180 / pi;
            e = (y - ry) / p;
            v = asin(e) * 180 / pi;
            v = v - s;
            ans += pi * 2 * r * (v + 90) / 360;
        }
        printf("%.4f\n", ans);
    }
}
 
————————————————
版权声明:本文为CSDN博主「sugarbliss」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/sugarbliss/article/details/90637103

QAQ,虽然·我也好奇我为啥可以写这么长,实力不允许吧,哈哈哈

#include<bits/stdc++.h>
using namespace std;
const double eps = 1e-8;
const double PI = atan(1.0)*4;
//判断x是否等于0
int sgn(double x){
    if(fabs(x) < eps) return 0;
    else return x < 0 ? -1:1;
}
//定义点及其基本运算
struct Point{
    double x, y;
    Point(){}
    Point(double x, double y):x(x),y(y){}
    Point operator + (Point B){return Point(x+B.x,y+B.y);}
    Point operator - (Point B){return Point(x-B.x,y-B.y);}
    Point operator * (double k){return Point(x*k,y*k);}
    Point operator / (double k){return Point(x/k,y/k);}
};
typedef Point Vector; //定义向量
double Dot(Vector A, Vector B){return A.x*B.x+A.y*B.y;} //点积
double Len(Vector A){return sqrt(Dot(A,A));}//向量的长度
double Len2(Vector A){return Dot(A,A);}//向量长度的平方
double Cross(Vector A, Vector B){return A.x*B.y-A.y*B.x;}//叉积
double Distance(Point A, Point B){return hypot(A.x-B.x,A.y-B.y);}
double Angle(Vector A, Vector B){return acos(Dot(A,B)/Len(A)/Len(B));}
double get_arc(double d, double r){return d * r;}
struct Line{
    Point p1, p2;
    Line(){}
    Line(Point p1, Point p2):p1(p1),p2(p2){}
    Line(double a, double b, double c){
        if(sgn(a) == 0){
            p1 = Point(0, -c/b);
            p2 = Point(1, -c/b);
        }
        else if(sgn(b) == 0){
            p1 = Point(-c/a, 0);
            p2 = Point(-c/a, 1);
        }
        else {
            p1 = Point(0, -c/b);
            p2 = Point(1, (-c-a)/b);
        }
    }
};
double Dis_point_line(Point p, Line v){//点到直线的距离
    return fabs(Cross(p - v.p1,v.p2 - v.p1))/Distance(v.p1, v.p2);
}
struct Circle{
    Point c;
    double r;
    Circle(){}
    Circle(Point c, double r):c(c),r(r){}
    Circle(double x, double y, double _r){c = Point(x,y), r = _r;}
};
int Line_circle_relation(Line v, Circle C){
    double dst = Dis_point_line(C.c, v);
    if(sgn(dst - C.r) < 0) return 0;
    if(sgn(dst - C.r) == 0) return 1;
    return 2;
}
Point Point_line_proj(Point p, Line v){//点在直线上的投影
    double k = Dot(v.p2 - v.p1, p - v.p1)/Len2(v.p2 - v.p1);
    return v.p1 + (v.p2-v.p1)*k;
}

//直线和圆的交点,pa,pb是交点,返回值是焦点的个数
int Line_cross_circle(Line v, Circle C, Point &pa, Point &pb){
    if(Line_circle_relation(v, C) == 2) return 0;//无交点
    Point q = Point_line_proj(C.c, v);//圆心在直线上的投影点
    double d = Dis_point_line(C.c, v);//圆心到直线的距离
    double k = sqrt(C.r*C.r-d*d);
    if(sgn(k) == 0){//一个交点,直线与圆相切
        pa = q; pb = q; return 1;
    }
    Point n = (v.p2 - v.p1)/Len(v.p2 - v.p1);//单位向量
    pa = q + n * k;
    pb = q - n * k;
    return 2;//两个交点
}
int main(){
    int T;
    scanf("%d", &T);
    while(T --){
        double rx ,ry, r, x, y;
        scanf("%lf%lf%lf%lf%lf", &rx, &ry, &r, &x, &y);
        double arc_length = PI/2.0*r;
        if(x <= rx - r || x >= rx + r){//x = rx-r 或x = rx + r 左右, 距离等于四分之一圆加两点距离
            double xx = (x >= rx)?rx + r:rx - r;
            Point A = {x, y}, B = {xx, ry};
            arc_length += Distance(A, B);
        }
        else {//否则是劣弧的弧长+切点到目标点的距离
            Point pa, pb;
            Vector A = {x - rx, y - ry};
            Circle C = {rx, ry, r};
            double rr2 = Len2(A)-r*r;
            Line v = {2*(x - rx), 2*(y - ry), rx*rx+ry*ry-x*x-y*y-r*r+rr2};
            if(Line_cross_circle(v, C, pa, pb) > 0){
                double xx = (x >= rx)?rx + r:rx - r;
                Point a = {x, y}, b = {xx, ry};
                if(x >= rx){//判断劣弧
                    Vector E = {r, 0}, F = {pa.x-rx, pa.y-ry};
                    arc_length += Distance(pa, a);
                    double d = Angle(E, F);
                    arc_length += get_arc(d, r);
                }
                else{
                    Vector E = {-r, 0}, F = {pb.x-rx, pb.y-ry};
                    arc_length += Distance(pb, a);
                    double d = Angle(E, F);
                    arc_length += get_arc(d, r);
                }
            } 
        }
        printf("%.4lf\n", arc_length);
    }
    return 0;
}

希望这只弱鸡也能有把代码写的高深莫测的那一天…

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

marx97 ٩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值