原题链接:
HDU-6097
大意:
院内有两点
P
,
官方题解:
思路:
点关于圆的反演。
关于反演的知识:
中文词条名:反演点
英文词条名:inverse point
一般指二维反演中的点。
二维上反演以一个特定的反演圆为基础:圆心
O
为反演中心,圆半径为常数
OP×OP′=r2
如点 P 在圆外可这样作:过点
如点 P 在圆内就把这一过程反过来即可:连结
如点P在圆上,反演后仍是它自身.按上述方法都可用尺规作图完成.
设点M关于圆的反演点是 N ,则该圆上任意一点
PMPN=OMON−−−−√
;
两个块级公式比较重要。构造过程也要掌握。
做出反演点,把
DP
转化成
DP′
来求,所以转化成求
P′Q′
与圆是否有交点, 若存在则为交点处为
D
具体公式是
上图吧
代码都是数学公式
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mem(s,t) memset(s,t,sizeof(s))
//#define D(v) cout<<#v<<" "<<v<<endl
#define inf 0x3f3f3f3f
//#define LOCAL
inline void read(int &x){
x=0;char p=getchar();
while(!(p<='9'&&p>='0'))p=getchar();
while(p<='9'&&p>='0')x*=10,x+=p-48,p=getchar();
}
double sq(double x){return x*x;}
double dis(double a,double b,double c,double d){return sqrt(sq(a-c)+sq(b-d));}
bool check(double a,double b,double c){
if(sq(a)+sq(b)<=sq(c))return 1;
if(sq(b)+sq(c)<=sq(a))return 1;
if(sq(a)+sq(c)<=sq(b))return 1;
return 0;
}
int main() {
#ifdef LOCAL
freopen("1002.in","r",stdin);
freopen("out.txt","w",stdout);
#endif
int t;
read(t);
while(t--){
double r,x1,y1,x2,y2;
scanf("%lf%lf%lf%lf%lf",&r,&x1,&y1,&x2,&y2);
double x0=(x1+x2)/2;
double y0=(y1+y2)/2;
double r0=dis(x1,y1,0,0);
if(r0==0){
printf("%lf\n",2*r);
continue;
}
double rr=sq(r)/r0;
double xp=rr/r0*x1,xq=rr/r0*x2;
double yp=rr/r0*y1,yq=rr/r0*y2;
double rt=dis(x0,y0,0,0);
double xm=r/rt*x0;
double ym=r/rt*y0;
double PM=dis(xp,yp,xm,ym);
if(check(PM,r,rr)){
printf("%.7lf\n",2*dis(xm,ym,x1,y1));
}else {
double lambda=sqrt(r0/rr);
printf("%.7lf\n",lambda*dis(xp,yp,xq,yq));
}
}
return 0;
}