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 @   ViKyanite  阅读(43)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· winform 绘制太阳,地球,月球 运作规律
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
历史上的今天:
2020-03-15 烟花
2020-03-15 简单字母闪烁
2020-03-15 文字左右横移
点击右上角即可分享
微信分享提示
主题色彩