zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    设计模式学习总结系列应用实例
    【研究课题】高校特殊学生的发现及培养机制研究
    Linux下Oracle11G RAC报错:在安装oracle软件时报file not found一例
    python pro practice
    openstack python sdk list tenants get token get servers
    openstack api
    python
    git for windows
    openstack api users list get token get servers
    linux 流量监控
  • 原文地址:https://www.cnblogs.com/Vikyanite/p/14536966.html
Copyright © 2011-2022 走看看