hdu 6097 Mindis

来源:互联网 发布:centos 6.8 搭建lnmp 编辑:程序博客网 时间:2024/06/14 04:13

传送门



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
444 00 440 33 040 22 040 11 0
 

Sample Output
5.65685435.65685435.89450306.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 doubletypedef 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 _ixvii0ivusing 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 doubletypedef 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);        }    }}