做P点关于圆的反演点P’,OPD与ODP’相似,相似比是|OP| : r。
Q点同理。
极小化PD+QD可以转化为极小化P’D+Q’D。
当P’Q’与圆有交点时,答案为两点距离,否则最优值在中垂线上取到。
时间复杂度 O(1)
具体图形看这个博客http://blog.csdn.net/qq_34845082/article/details/77099332
以下是代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdlib>
#include <cctype>
#include <string>
#include <iostream>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <ctime>
using namespace std;
typedef long long ll;
const int N = 3e5+5;
const double eps = 1e-8;
struct node
{
double x,y;
};
int main()
{
int t ;
scanf("%d",&t);
while(t--)
{
double r ;
scanf("%lf",&r);
node a,b;
node a1,b1;
scanf("%lf%lf%lf%lf",&a.x,&a.y,&b.x,&b.y);
double dis1 = sqrt(a.x*a.x+a.y*a.y);
if(dis1<eps)
{
printf("%.7f\n",2*r );
continue ;
}
double kk = r*r/dis1/dis1;
a1.x=kk*a.x;a1.y=a.y*kk;b1.x=kk*b.x;b1.y=kk*b.y;
node mid ;
mid.x = (a1.x + b1.x)/2 ;
mid.y = (a1.y + b1.y)/2 ;
double dis = sqrt(mid.x*mid.x + mid.y*mid.y);
double ans ;
if(dis<=r)
ans = sqrt((a1.x-b1.x)*(a1.x-b1.x)+(a1.y-b1.y)*(a1.y-b1.y))
ans = ans*dis1/r;
else
{
double temp = r/dis;
node ans1 ; ans1.x=temp*mid.x;ans1.y=temp*mid.y;
ans=2*sqrt((ans1.x-a.x)*(ans1.x-a.x)+(ans1.y-a.y)*(ans1.y-a.y));
}
printf("%.7f\n",ans );
}
return 0 ;
}