HDU 6097 Mindis【计算几何+反演点】

题目链接

题意:有一个圆心在原点,半径为 r 的圆,圆内有两点P, Q 到圆心的距离相同,在圆上找一点D,使 |DP|+|DQ| 最小。求这个最小值。

当然不是直接取中垂线这么简单啊……

反演点:
已知圆 O 的半径为R,从圆心 O 出发任作一射线,在射线上任取两点M,N。若 |OM|=m |ON|=n ,且 mn=R2 ,则称点 M,N 是关于圆 O 的反演点。M,N关于圆 O 的一个变换叫做反演变换。——百度百科

所以就是延长OP OQ ,分别取 P Q 使 |OP||OP|=r2 |OQ||OQ|=r2 ,则 ODPOPD ODQOQD |DP| |DQ| |PD| |QD| 是成比例的。所以只要使 |PD|+|QD| 极小就行。

所以 PQ 这条直线和圆有交点的时候,当然是取交点为 D 啦。否则的话,就是中垂线和圆的交点为D

放两个从网上盗的图。

$P^{'}Q^{'}$和圆不相交的情况

$P^{'}Q^{'}$和圆相交的情况

#include <bits/stdc++.h>
using namespace std;

const double eps=1e-8;

int T;
double r,X1,Y1,X2,Y2;

int main(){
    scanf("%d",&T);
    while (T--){
        scanf("%lf %lf %lf %lf %lf",&r,&X1,&Y1,&X2,&Y2);
        double d0=sqrt(X1*X1+Y1*Y1);
        if (fabs(d0)<eps){
            printf("%.7f\n",2*r);
            continue;
        }
        double k=(r*r)/(d0*d0);
        double xx1=k*X1,yy1=k*Y1,xx2=k*X2,yy2=k*Y2;
        double mx=(xx1+xx2)/2.0;
        double my=(yy1+yy2)/2.0;
        double d=sqrt(mx*mx+my*my);
        double ans=0;
        if (d<=r){
            double dist=sqrt((xx1-xx2)*(xx1-xx2)+(yy1-yy2)*(yy1-yy2));
            ans=dist*d0/r;
        }
        else{
            double tx,ty;
            tx=mx*r/d;
            ty=my*r/d;
            ans=2*sqrt((tx-X1)*(tx-X1)+(ty-Y1)*(ty-Y1));
        }
        printf("%.7f\n",ans);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值