hdu 6097 Mindis(几何反演)

本文介绍了一个基于几何反演原理的算法问题——寻找一点D位于给定圆上,使得该点到圆内两点P和Q的距离之和最小。通过分析不同情况下P'Q'与圆的位置关系,给出了具体的实现代码。

Mindis

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 2598    Accepted Submission(s): 497
Special Judge

 

Problem Description

The center coordinate of the circle C is O, the coordinate of O is (0,0) , and the radius is r.
P and Q are two points not outside the circle, and PO = QO.
You need to find a point D on the circle, which makes PD+QD minimum.
Output minimum distance sum.

 

 

Input

The first line of the input gives the number of test cases T; T test cases follow.
Each case begins with one line with r : the radius of the circle C.
Next two line each line contains two integers x , y denotes the coordinate of P and Q.

Limits
T≤500000
−100≤x,y≤100
1≤r≤100

 

 

Output

For each case output one line denotes the answer.
The answer will be checked correct if its absolute or relative error doesn't exceed10−6.
Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if|ab|max(1,b)≤10−6.

 

 

Sample Input

 

4 4 4 0 0 4 4 0 3 3 0 4 0 2 2 0 4 0 1 1 0

 

 

Sample Output

5.6568543
5.6568543
5.8945030
6.7359174

 

 

 

 

 

 

 

 

 

根据几何反演,将OP,OQ沿P,Q延长,使OP*OP'=r*r,OQ*OQ'=r*r

 

△ODP∽△OP'D  x=DP/DP'=OP/OD=OD/OP'=|OP|/r

 

P'Q'/PQ=OP'/OP=(r*r)/(|OP|*|OP|)

 

(P'D+Q'D)=(PD*x+QD*x)=x*(ans)

ans为所求答案

 

第一种情况:P'Q'与圆有交点
D是P'Q'与圆的交点

 

P'D'+Q'D'=P'Q'


第二种情况:P'Q'与圆没有交点
D是P'Q'中垂线与圆的交点(因为P,Q是关于O中心对称的,所以P',Q'也与0中心对称,所以P'Q'的中垂线一定过O)
W是P'Q'的中点

 

P'D'+Q'D=2*P'D=2*√P'Q'^2+(OW-r)^2

 

 

 

#include<cstdio>
#include<cstring>
#include<stdlib.h>
#include<cmath>
using namespace std;

int r,px,py,qx,qy;

int main()
{
	int t;
	scanf("%d",&t);
	while(t--)
	{
		scanf("%d",&r);
		scanf("%d%d",&px,&py);
		scanf("%d%d",&qx,&qy);

		long long int a,b;
		a=px*px+py*py;    //OP,OQ
		b=(px-qx)*(px-qx)+(py-qy)*(py-qy);  //PQ
		double ans;

		if(r*r*(4*a-b)<=4*a*a)    //p'q'与圆有交点
		{
			if(a==0) ans=(double)2*r;   //若p,q都在圆心
			else
			{
				double pq=r*r*b*1.0/a;   
				ans=sqrt(pq);
			}
		}
		else
		{
			double tmp=r*r+a-r*sqrt(4*a-b);
			ans=sqrt(tmp)*2;
		}
		printf("%.7lf\n",ans);
	}
	return 0;
}

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值