• Mindis HDU


    题意:给你一个圆,其圆心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
    ",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
    ", len);
        }
        return 0;
    }
  • 相关阅读:
    OpenJDK源码研究笔记(十二):JDBC中的元数据,数据库元数据(DatabaseMetaData),参数元数据(ParameterMetaData),结果集元数据(ResultSetMetaDa
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 257 二叉树的所有路径
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 242 有效的字母异位词
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
    Java实现 LeetCode 241 为运算表达式设计优先级
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/14536966.html
Copyright © 2020-2023  润新知