hdu 6097 Mindis

传送门



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
T500000
100x,y100
1r100
 

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  106 .
Formally, let your answer be a, and the jury's answer be b. Your answer is considered correct if  |ab|max(1,b)106 .
 

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
 

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);
        }

    }
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值