Loading

Mindis HDU - 6097

题意:给你一个圆,其圆心O在(0,0),给出圆的半径R, 之后再给出圆内两点P,Q,满足|PO| = |QO|,在圆上找到一点D使得|QD| + |PD|最小。

思路:进行P和Q对这个圆的反演可以得到P'和Q'。易得|QD| + |PD|就是求|Q'D| + |P'D|的最小值(相似三角形)。之后分类讨论即可

注意特判P = Q的情况。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
using namespace std;
const double eps = 1e-8;

int sgn(double x) {
    if (fabs(x) < eps) return 0;
    return x < eps ? -1 : 1;
}
struct Point{
    double x,y;
    Point(){}
    Point(double _x,double _y){
        x = _x;
        y = _y;
    }
    void input(){
        scanf("%lf%lf",&x,&y);
    }
    void output(){
        printf("%.2f %.2f\n",x,y);
    }
    bool operator == (Point b)const{
        return sgn(x-b.x) == 0 && sgn(y-b.y) == 0;
    }
    bool operator < (Point b)const{
        return sgn(x-b.x)== 0?sgn(y-b.y)<0:x<b.x;
    }
    Point operator -(const Point &b)const{
        return Point(x-b.x,y-b.y);
    }
    //叉积
    double operator ^(const Point &b)const{
        return x*b.y - y*b.x;
    }
    //点积
    double operator *(const Point &b)const{
        return x*b.x + y*b.y;
    }
    //返回长度
    double len(){
        return hypot(x,y);//库函数
    }
    //返回长度的平方
    double len2(){
        return x*x + y*y;
    }
    //返回两点的距离
    double distance(Point p){
        return hypot(x-p.x,y-p.y);
    }
    Point operator +(const Point &b)const{
        return Point(x+b.x,y+b.y);
    }
    Point operator *(const double &k)const{
        return Point(x*k,y*k);
    }
    Point operator /(const double &k)const{
        return Point(x/k,y/k);
    }

};
struct Circle{
    Point p;//圆心
    double r;//半径
    Circle(){}
};

/* 直线和原的交点 */
int getLineCircleIntersection (Point p, Point q, Circle O, vector<Point>& sol) {
    double t1, t2;
    Point v = q - p;
    sol.clear();

    double a = v.x, b = p.x - O.p.x, c = v.y, d = p.y - O.p.y;
    double e = a*a+c*c, f = 2*(a*b+c*d), g = b*b+d*d-O.r*O.r;
    double delta = f*f - 4*e*g;
    if (sgn(delta) < 0) return 0;
    if (sgn(delta) == 0) {
        t1 = t2 = -f / (2 * e);
        sol.push_back(p + v * t1);
        return 1;
    }

    t1 = (-f - sqrt(delta)) / (2 * e); sol.push_back(p + v * t1);
    t2 = (-f + sqrt(delta)) / (2 * e); sol.push_back(p + v * t2);
    return 2;
}

int main() {
    int T; scanf("%d", &T);
    while (T--) {
        Circle O;
        scanf("%lf", &O.r);
        Point p, q;
        p.input(), q.input();
        Point pp, qq;
        pp = p * (O.r*O.r / p.len() / p.len());
        qq = q * (O.r*O.r / q.len() / q.len());
        Point mid = (p + q) / 2.0;
        mid = mid * (O.r / mid.len());
        vector<Point> CrossP;
        int num = getLineCircleIntersection(pp, qq, O, CrossP);
        double len;
        if (p == q) len = 2.0*(O.r - q.len());
        else if (num) len = (CrossP[0]-p).len() + (CrossP[0]-q).len();
        else len = 2.0*(mid-p).len();
        printf("%.7f\n", len);
    }
    return 0;
}

 

posted @ 2021-03-15 13:00  ViKyanite  阅读(42)  评论(0编辑  收藏  举报