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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 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 文字左右横移