• 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;
    }
  • 相关阅读:
    NC外部统一流程管理平台方案
    Activiti 多个并发子流程的应用
    基于Activiti的流程应用开发平台JSAAS-WF V5.3
    整合Acitiviti在线流程设计器(Activiti-Modeler 5.18.0)
    基于Spring Security 的JSaaS应用的权限管理
    微信分享功能开发
    ORACLE schedule job设置
    存储过程清理N天前数据
    oracle函数trunc的使用
    往前往后推时间(排除工作日和节假日)
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/14536966.html
Copyright © 2020-2023  润新知