GYM 101617 F

说到这题还要提到周日下午训练赛,都进去了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 }
View Code
原文地址:https://www.cnblogs.com/MXang/p/10760063.html