您的位置:首页 > 其它

hdu 6097 Mindis

2017-08-10 23:08 357 查看
传送门

Mindis

Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)

Total Submission(s): 1182    Accepted Submission(s): 135
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 exceed 10−6.

Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if |a−b|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

 

Source

2017 Multi-University Training Contest - Team 6
 

Recommend

liuyiding   |   We have carefully selected several similar problems for you:  6107 6106 6105 6104 6103 
题意:

圆心 O 坐标(0, 0), 给定两点 P, Q(不在圆外),满足 PO = QO,

要在圆上找一点 D,使得 PD + QD 取到最小值。

此题会补充三种做法:
1.椭圆


第一定义

平面内与两定点

 

 


 

 
的距离的和等于常数

 

 


 

 
)的动点P的轨迹叫做椭圆,即:



第二定义

椭圆平面内到定点
 

 
(c,0)的距离和到定直线
 

 

 

 

 

 
不在
 

 
上)的距离之比为常数
 

 
(即离心率
 

 
,0<e<1)的点的轨迹是椭圆。

其中定点
 

 
为椭圆的焦点[5]  ,定直线
 

 
称为椭圆的准线(该定直线的方程是
 

 
(焦点在x轴上),或
 

 
(焦点在y轴上))。

其他定义

根据椭圆的一条重要性质:椭圆上的点与椭圆长轴(事实上只要是直径都可以)两端点连线的斜率之积是定值,定值为
 

 
(前提是长轴平行于x轴。若长轴平行于y轴,比如焦点在y轴上的椭圆,可以得到斜率之积为 -a²/b²=1/(e²-1)),可以得出:

坐标轴内,动点(
 

 
)到两定点(
 

 
)(
 

 
)的斜率乘积等于常数m(-1<m<0)

注意:考虑到斜率不存在时不满足乘积为常数,所以
 

 
无法取到,即该定义仅为去掉两个点的椭圆。

令PQ为椭圆的焦点。那么PQ=2c c显然可以得到,对离心率e二分,直到直到满足条件的e,对于一个椭圆来说,椭圆上的点到两焦点的距离2a,所以如果我能找到一个合适的离心率构造出椭圆,最后答案就是2a,但我得满足这个椭圆与圆有交点,不然取不到圆上的点。c是固定值,如果我要改变e,a是未知值,我只能改变b,使离心率改变,所以就有了如下代码。

//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=2e2+10;
const int maxx=1e4+100;
const double EPS=1e-7;
const int mod=10000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
inline LL Scan()
{
int f=1;char C=getchar();LL x=0;
while (C<'0'||C>'9'){if (C=='-')f=-f;C=getchar();}
while (C>='0'&&C<='9'){x=x*10+C-'0';C=getchar();}
x*=f;return x;
}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.out" , "w" , stdout );
//cerr << "run time is " << clock() << endl;

struct Point
{
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) { }
inline void input()
{
scanf("%lf%lf",&x,&y);
}
inline void print()
{
printf("%.6lf %.6lf\n",x,y);
}
};
db r;
db dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
int megumi(db e,db c,db B,db r)//e为离心率
{
db y=(1-e*e)/(e*e)*B;//椭圆上一点且该点为切点
db a=c/e;
db b=sqrt(a*a-c*c);
if(y>b) return (b+B>r);
double x2=a*a*(1-y*y/(b*b));//x^2
return (x2+(y+B)*(y+B)>r*r)||(B+b>r);//判断条件
}

int main()
{
int t;
t=Scan();
while(t--)
{
scanf("%lf",&r);
Point a,b;
Point O={0,0};
a.input(),b.input();
double o1=dis(O,a),o2=dis(O,b),o12=dis(a,b);
if(fabs(o1-r)<1e-4||fabs(o2-r)<1e-4)//有一个点在圆上
{
printf("%.7f\n",o12);
continue;
}
else if(fabs(o12-o1-o2)<1e-4)//同在圆心
{
printf("%.7f\n",2*r);
continue;
}
else if(fabs(o12)<1e-4)//P Q重点
{
printf("%.7f\n",2*(r-o1));
continue;
}
db c=o12/2;
db B=sqrt(o1*o1-c*c);
db l=1e-9,rr=1;
//cout<<c<<" "<<B<<endl;
int len=35;
while(len--)
{
double m=(l+rr)/2;
if(megumi(m,c,B,r)) l=m;
else rr=m;
}
printf("%.7f\n",c/l*2);//2a
}
}

2.黄金分割三分(不会,只有一份用map的)

为啥可以map呢,-100到100所以可以map

#include<cstdio>
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<map>
#include<cmath>
#include<vector>
#include<stack>
#include<climits>
#include<ctime>
#include<queue>
#define FILEIN freopen("in.txt", "r", stdin)
#define FILEOUT freopen("out.txt", "w", stdout)
#define CLOSEIO ios::sync_with_stdio(false)
#define PI acos(-1)
#define CLR(a) memset(a,0,sizeof(a))
#define MEM(a,x) memset(a,x,sizeof(a))
#define eps 1e-8
#define sf(x) scanf("%d",&x)
#define PB(x) push_back(x)
#define MP(x, y) make_pair(x, y)
#define lowbit(x) x&(-x)
#define fi first
#define se second
#define rep(a,b,c) for(int (a)=(b);(a)<(c);(a)++)
#define drep(a,b,c) for(int (a)=(b);(a)>(c);--(a))
#define dbg(x) cout << #x << "=" << x << endl
#define _ixvii0iv
using namespace std;
const int maxn = 1e5+5;
typedef long long ll;
typedef double db;
const int inf = INT_MAX;
const ll INF = LLONG_MAX;
const ll mod = 1e9 + 7;
ll mul(ll x,ll y){return x*y%mod;}
ll q_mul(ll a, ll b){ ll ans = 0;while(b){if(b & 1){ans=(ans+a)%mod;} b>>=1;a=(a+a) % mod;}return ans;}
ll q_pow(ll x , ll y){ll res=1;while(y){if(y&1) res=q_mul(res,x) ; y>>=1 ; x=q_mul(x,x);} return res;}
ll inv(ll x) { return q_pow(x, mod-2); }
int Read() {
int x = 0, F = 1; char C = getchar();
while (C < '0' || C > '9') { if (C == '-') F = -F; C = getchar(); }
while (C >= '0' && C <= '9') { x = x * 10 - '0' + C, C = getchar(); }
return x * F;

}
struct vis{
int r;
int R;
int len;
bool operator<(const vis &a)const{
if(r!=a.r)
return r<a.r;
else if(R!=a.R)
return R<a.R;
else return len<a.len;
}
bool operator=(const vis &a)const{
return r==a.r&&R==a.R&&len==a.len;
}
};
map<vis,db>mp;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
#define ll long long
//fread->read
bool IOerror=0;
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if (p1==pend){
p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin);
if (pend==p1){IOerror=1;return -1;}
//{printf("IO error!\n");system("pause");for (;;);exit(0);}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
inline void read(int &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (sign)x=-x;
}

inline void read(double &x){
bool sign=0; char ch=nc(); x=0;
for (;blank(ch);ch=nc());
if (IOerror)return;
if (ch=='-')sign=1,ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if (ch=='.'){
double tmp=1; ch=nc();
for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');
}
if (sign)x=-x;
}
inline void read(char *s){
char ch=nc();
for (;blank(ch);ch=nc());
if (IOerror)return;
for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
}
inline void read(char &c){
for (c=nc();blank(c);c=nc());
if (IOerror){c=-1;return;}
}
//getchar->read
inline void read1(int &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(ll &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (bo)x=-x;
}
inline void read1(double &x){
char ch;int bo=0;x=0;
for (ch=getchar();ch<'0'||ch>'9';ch=getchar())if (ch=='-')bo=1;
for (;ch>='0'&&ch<='9';x=x*10+ch-'0',ch=getchar());
if (ch=='.'){
double tmp=1;
for (ch=getchar();ch>='0'&&ch<='9';tmp/=10.0,x+=tmp*(ch-'0'),ch=getchar());
}
if (bo)x=-x;
}
inline void read1(char *s){
char ch=getchar();
for (;blank(ch);ch=getchar());
for (;!blank(ch);ch=getchar())*s++=ch;
*s=0;
}
inline void read1(char &c){for (c=getchar();blank(c);c=getchar());}
//scanf->read
inline void read2(int &x){scanf("%d",&x);}
inline void read2(ll &x){
#ifdef _WIN32
scanf("%I64d",&x);
#else
#ifdef __linux
scanf("%lld",&x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void read2(double &x){scanf("%lf",&x);}
inline void read2(char *s){scanf("%s",s);}
inline void read2(char &c){scanf(" %c",&c);}
inline void readln2(char *s){gets(s);}
//fwrite->write
struct Ostream_fwrite{
char *buf,*p1,*pend;
Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;}
void out(char ch){
if (p1==pend){
fwrite(buf,1,BUF_SIZE,stdout);p1=buf;
}
*p1++=ch;
}
void print(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(int x){
static char s[15],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1);
}
void println(ll x){
static char s[25],*s1;s1=s;
if (!x)*s1++='0';if (x<0)out('-'),x=-x;
while(x)*s1++=x%10+'0',x/=10;
while(s1--!=s)out(*s1); out('\n');
}
void print(double x,int y){
static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000,
1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL,
100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL};
if (x<-1e-12)out('-'),x=-x;x*=mul[y];
ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1;
ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2);
if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i); print(x3);}
}
void println(double x,int y){print(x,y);out('\n');}
void print(char *s){while (*s)out(*s++);}
void println(char *s){while (*s)out(*s++);out('\n');}
void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}}
~Ostream_fwrite(){flush();}
}Ostream;
inline void print(int x){Ostream.print(x);}
inline void println(int x){Ostream.println(x);}
inline void print(char x){Ostream.out(x);}
inline void println(char x){Ostream.out(x);Ostream.out('\n');}
inline void print(ll x){Ostream.print(x);}
inline void println(ll x){Ostream.println(x);}
inline void print(double x,int y){Ostream.print(x,y);}
inline void println(double x,int y){Ostream.println(x,y);}
inline void print(char *s){Ostream.print(s);}
inline void println(char *s){Ostream.println(s);}
inline void println(){Ostream.out('\n');}
inline void flush(){Ostream.flush();}
//puts->write
char Out[OUT_SIZE],*o=Out;
inline void print1(int x){
static char buf[15];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(int x){print1(x);*o++='\n';}
inline void print1(ll x){
static char buf[25];
char *p1=buf;if (!x)*p1++='0';if (x<0)*o++='-',x=-x;
while(x)*p1++=x%10+'0',x/=10;
while(p1--!=buf)*o++=*p1;
}
inline void println1(ll x){print1(x);*o++='\n';}
inline void print1(char c){*o++=c;}
inline void println1(char c){*o++=c;*o++='\n';}
inline void print1(char *s){while (*s)*o++=*s++;}
inline void println1(char *s){print1(s);*o++='\n';}
inline void println1(){*o++='\n';}
inline void flush1(){if (o!=Out){if (*(o-1)=='\n')*--o=0;puts(Out);}}
struct puts_write{
~puts_write(){flush1();}
}_puts;
inline void print2(int x){printf("%d",x);}
inline void println2(int x){printf("%d\n",x);}
inline void print2(char x){printf("%c",x);}
inline void println2(char x){printf("%c\n",x);}
inline void print2(ll x){
#ifdef _WIN32
printf("%I64d",x);
#else
#ifdef __linux
printf("%lld",x);
#else
puts("error:can't recognize the system!");
#endif
#endif
}
inline void println2(ll x){print2(x);printf("\n");}
inline void println2(){printf("\n");}
#undef ll
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace fastIO;
struct point
{
db x,y;
point() {};
point (db _x,db _y)
{
x = _x;
y = _y;
}
inline void input()
{
read(x);
read(y);
}
};
inline int sgn(db x)
{
return x<-eps?-1:x>eps?1:0;
}
typedef point line;
inline db Dot(line a,line b)
{
return a.x*b.x+a.y*b.y;
}
inline line operator +(line a,line b)
{
return line(a.x+b.x,a.y+b.y);
}
inline line operator -(line a,line b)
{
return line(a.x-b.x,a.y-b.y);
}
inline line operator *(line b,db a)
{
return line(b.x*a,b.y*a);
}

inline db len(line a)
{
return sqrt(Dot(a,a));
}
inline db Dis(point a,point b){
return len(b-a);
}
inline line Rotate(line a,db rad)//rad是弧度 负数表示顺时针 正数表示逆时针
{
db cr =cos(rad);
db sr = sin(rad);
return line(a.x*cr-a.y*sr,a.x*sr+a.y*cr);
}
struct circle{
point c;
double r;
circle() {}
circle(point _c,double _r){
c = _c;
r = _r;
}
inline void input(){
c.input();
read(r);
}
};
typedef point line;
int main(){
//FILEIN;
//FILEOUT;
int t = Read();
int ca = 1;
mp.clear();
while(t--){
db R;
point a,b;
read(R);
a.input();
b.input();
int rr = a.x*a.x+a.y*a.y;
int RR = R*R;
int lenn = (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
//cout << rr << " " << RR <<" " <<lenn << endl;
if(!(a.x-b.x)&&!(a.y-b.y)){
println(2*(R-len(a)),7);
continue;
}
if(!(a.x+b.x)&&!(a.y+b.y)||!a.x&&!a.y){
println(2*R,7);
continue;
}
vis vs;
vs.R = RR;
vs.r = rr;
vs.len = lenn;
if(mp[vs]){
println(mp[vs],7);
continue;
}
point mab;
mab.x = (a.x+b.x)/2.0;
mab.y = (a.y+b.y)/2.0;
line mm = mab;
db l = 0; db r = PI;
int tm = 0;
db x = R/len(mm);
mm.x*=x;
mm.y*=x;
db diss;
while(r-l>eps){
if(tm>50) break;
db mid1 = (l+r)/2.0;
db mid2 = (r+mid1)/2.0;
line l1 = Rotate(mm,mid1);
line l2 = Rotate(mm,mid2);
db dis1 = Dis(l1,a)+Dis(l1,b);
db dis2 = Dis(l2,a)+Dis(l2,b);
if(sgn(dis2-dis1)>0) r = mid2,diss = dis1;
else l = mid1,diss = dis2;
tm++;
}
mp[vs] = diss;
println(diss,7);
//puts("");

}

}

3.反演

反演:

设在平面内给定一点O和常数k(k不等于零),对于平面内任意一点A,确定A′,使A′在直线OA上一点,并且有向线段OA与OA′满足OA·OA′=k,我们称这种变换是以O为的反演中心,以k为反演幂的反演变换,简称反演。——百度百科

DP+DQ=(DP'+DQ')*k

当 P'Q' 与圆有交点时:

不妨设交点为 O',若 D 不为 O',则 P'D + Q'D >  P'Q'(三角形两边之和大于第三边);当且仅当 D 取 O' 时,P'Q + Q'D 取到最小值,即为 P'Q'。

当 P'Q' 与圆无交点时:

 PQ 的中垂线与圆的交点一定是使得DP'+DQ'最小的点。OQ'=OP',且DP'=DQ',请仔细想想这个为什么。

//china no.1
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <vector>
#include <iostream>
#include <string>
#include <map>
#include <stack>
#include <cstring>
#include <queue>
#include <list>
#include <stdio.h>
#include <set>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <iomanip>
#include <cctype>
#include <sstream>
#include <functional>
#include <stdlib.h>
#include <time.h>
#include <bitset>
using namespace std;

#define pi acos(-1)
#define endl '\n'
#define srand() srand(time(0));
#define me(x,y) memset(x,y,sizeof(x));
#define foreach(it,a) for(__typeof((a).begin()) it=(a).begin();it!=(a).end();it++)
#define close() ios::sync_with_stdio(0); cin.tie(0);
#define FOR(x,n,i) for(int i=x;i<=n;i++)
#define FOr(x,n,i) for(int i=x;i<n;i++)
#define W while
#define sgn(x) ((x) < 0 ? -1 : (x) > 0)
#define bug printf("***********\n");
#define db double
typedef long long LL;
const int INF=0x3f3f3f3f;
const LL LINF=0x3f3f3f3f3f3f3f3fLL;
const int dx[]={-1,0,1,0,1,-1,-1,1};
const int dy[]={0,1,0,-1,-1,1,-1,1};
const int maxn=2e2+10;
const int maxx=1e4+100;
const double EPS=1e-7;
const int mod=10000007;
template<class T>inline T min(T a,T b,T c) { return min(min(a,b),c);}
template<class T>inline T max(T a,T b,T c) { return max(max(a,b),c);}
template<class T>inline T min(T a,T b,T c,T d) { return min(min(a,b),min(c,d));}
template<class T>inline T max(T a,T b,T c,T d) { return max(max(a,b),max(c,d));}
inline LL Scan()
{
int f=1;char C=getchar();LL x=0;
while (C<'0'||C>'9'){if (C=='-')f=-f;C=getchar();}
while (C>='0'&&C<='9'){x=x*10+C-'0';C=getchar();}
x*=f;return x;
}
//freopen( "in.txt" , "r" , stdin );
//freopen( "data.out" , "w" , stdout );
//cerr << "run time is " << clock() << endl;

struct Point
{
double x, y;
Point(double x = 0, double y = 0) : x(x), y(y) { }
inline void input()
{
scanf("%lf%lf",&x,&y);
}
inline void print()
{
printf("%.6lf %.6lf\n",x,y);
}
};
db r;
db dis(Point a,Point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}

typedef Point Vector;

Vector operator + (Vector A, Vector B) { return Vector(A.x + B.x, A.y + B.y); }
Vector operator - (Vector A, Vector B) { return Vector(A.x - B.x, A.y - B.y); }
Vector operator * (Vector A, double p) { return Vector(A.x * p, A.y * p); }
Vector operator / (Vector A, double p) { return Vector(A.x / p, A.y / p); }

bool operator < (const Point& a, const Point b)
{
return a.x < b.x || (a.x == b.x && a.y < b.y);
}
int dcmp(double x)
{
if(fabs(x) < EPS) return 0;
else return x < 0 ? -1 : 1;
}

bool operator == (const Point& a, const Point& b)
{
return dcmp(a.x-b.x) == 0 && dcmp(a.y-b.y);
}
//向量点积
double Dot(Vector A, Vector B) { return A.x*B.x + A.y*B.y; }

//向量长度
double Length(Vector A) { return sqrt(Dot(A, A)); }

//向量叉积  |a||b|sin<a,b>
//叉积的结果也是一个向量,是垂直于向量a,b所形成的平面,如果看成三维坐标的话是在 z 轴上,上面结果是它的模。
double Cross(Vector A, Vector B) { return A.x*B.y - A.y*B.x; }

//点到直线的距离
double DistanceToLine(Point P, Point A, Point B)
{
Vector v1 = B - A, v2 = P - A;
return fabs(Cross(v1, v2) / Length(v1)); //不取绝对值,得到的是有向距离
}
int main()
{
//freopen( "in.txt" , "r" , stdin );
//freopen( "out.txt" , "w" , stdout );
int t;
t=Scan();
while(t--)
{
scanf("%lf",&r);
Point a,b;
Point O={0,0};
a.input(),b.input();
double o1=dis(O,a),o2=dis(O,b),o12=dis(a,b);
if(fabs(o1-r)<1e-4||fabs(o2-r)<1e-4)//有一个点在圆上
{
printf("%.10f\n",o12);
continue;
}
else if(fabs(o12-o1-o2)<1e-4)//圆心重合
{
printf("%.10f\n",2*r);
continue;
}
else if(fabs(o12)<1e-4)//P Q重点
{
printf("%.10f\n",2*(r-o1));
continue;
}
db k=o1/r;
db o11=(db)r*r/o1;//op'
db t=o11/o1;
Point p1={t*a.x,t*a.y};
Point q1={t*b.x,t*b.y};
db len=DistanceToLine(O,p1,q1);
if(dcmp(len-r)<=0)//p1q1与圆相交
{
printf("%.10f\n",dis(p1,q1)*k);
continue;
}
else
{
db h=len-r;
db d=dis(p1,q1)/2;
db ans=2*sqrt(h*h+d*d);
printf("%.10f\n",ans*k);
}

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: