说到这题还要提到周日下午训练赛,都进去了hmc说他这场单切过准备换一场。
很不幸的是我当时已经开了这个几何题,
开场就开几何是什么鬼啊!!!
给你n个圆,找一点在所有园内并且离原点最远。(保证有解)
我们肯定要援圆交啦!要素过多
其实我们可以大胆的猜测这个答案就在圆的交点上,
但是我们考虑到某种特殊情况,比方说只有一个圆,所以求一下原点与圆心的连线与圆的交点
再考虑到可能圆心就在原点上,特判一下,就ok了
1 // 2 // Created by gtx1080 on 2019-04-23. 3 // 4 #include <bits/stdc++.h> 5 using namespace std; 6 typedef double db; 7 typedef long long ll; 8 const db eps=1e-6; 9 const db pi=acos(-1); 10 int sign(db k){ 11 if (k>eps) return 1; else if (k<-eps) return -1; return 0; 12 } 13 int cmp(db k1,db k2){return sign(k1-k2);} 14 struct point{ 15 db x,y; 16 point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};} 17 point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};} 18 point operator * (db k1) const{return (point){x*k1,y*k1};} 19 int operator == (const point &k1) const{return cmp(x,k1.x)==0&&cmp(y,k1.y)==0;} 20 db abs(){return sqrt(x*x+y*y);} 21 db abs2(){return x*x+y*y;} 22 db dis(point k1){return ((*this)-k1).abs();} 23 point turn90(){return (point){-y,x};} 24 point unit(){db w=abs(); return (point){x/w,y/w};} 25 }; 26 db cross(point k1,point k2){return k1.x*k2.y-k1.y*k2.x;} 27 db dot(point k1,point k2){return k1.x*k2.x+k1.y*k2.y;} 28 point proj(point k1,point k2,point q){ // q 到直线 k1,k2 的投影 29 point k=k2-k1; return k1+k*(dot(q-k1,k)/k.abs2()); 30 } 31 struct circle{ 32 point o; db r; 33 int inside(point k){return cmp(r,o.dis(k))>=0;} 34 }; 35 int checkposCC(circle k1,circle k2){// 返回两个圆的公切线数量 36 if (cmp(k1.r,k2.r)==-1) swap(k1,k2); 37 db dis=k1.o.dis(k2.o); int w1=cmp(dis,k1.r+k2.r),w2=cmp(dis,k1.r-k2.r); 38 if (w1>0) return 4; else if (w1==0) return 3; else if (w2>0) return 2; 39 else if (w2==0) return 1; else return 0; 40 } 41 vector<point> getCC(circle k1,circle k2){// 沿圆 k1 逆时针给出 , 相切给出两个 42 int pd=checkposCC(k1,k2); if (pd==0||pd==4) return {}; 43 db a=(k2.o-k1.o).abs2(),cosA=(k1.r*k1.r+a-k2.r*k2.r)/(2*k1.r*sqrt(max(a,(db)0.0))); 44 db b=k1.r*cosA,c=sqrt(max((db)0.0,k1.r*k1.r-b*b)); 45 point k=(k2.o-k1.o).unit(),m=k1.o+k*b,del=k.turn90()*c; 46 return {m-del,m+del}; 47 } 48 vector<point> getCL(circle k1,point k2,point k3){ // 沿着 k2->k3 方向给出 , 相切给出两个 49 point k=proj(k2,k3,k1.o); db d=k1.r*k1.r-(k-k1.o).abs2(); 50 if (sign(d)==-1) return {}; 51 point del=(k3-k2).unit()*sqrt(max((db)0.0,d)); return {k-del,k+del}; 52 } 53 vector<point> mb,tmp; 54 void slove(circle a,circle b){ 55 if(checkposCC(a,b)){ 56 tmp = getCC(a,b); 57 mb.push_back(tmp[0]); 58 mb.push_back(tmp[1]); 59 } 60 } 61 void check(circle a){ 62 if(a.o==(point){0,0}) 63 return; 64 tmp = getCL(a,{0,0},a.o); 65 mb.emplace_back(tmp[0]); 66 mb.emplace_back(tmp[1]); 67 } 68 int n;circle c[55]; 69 db solve(point x){ 70 for(int i=1;i<=n;i++){ 71 if(!c[i].inside(x)) 72 return 0; 73 } 74 return x.abs(); 75 } 76 int main(){ 77 scanf("%d",&n); 78 db nxt=20000930; 79 for(int i=1;i<=n;i++){ 80 scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r); 81 if(c[i].o==(point){0,0})nxt=min(nxt,c[i].r); 82 } 83 for(int i=1;i<=n;i++){ 84 check(c[i]); 85 for(int j=i+1;j<=n;j++){ 86 slove(c[i],c[j]); 87 } 88 } 89 db ans = 0; 90 for(auto tmp:mb){ 91 // printf("%.11f %.11f ",tmp.x,tmp.y); 92 ans = max(ans,solve(tmp)); 93 } 94 if(cmp(ans,0)==0&&nxt!=20000930) 95 printf("%.3f ",nxt); 96 else 97 printf("%.3f ",ans); 98 }