poj 1375

一道解析几何么,,,

其实就是求直线与圆的切线。

看到方法有很多,比如根据角度之类的。

这里主要用到了初中的几何知识。

考虑这幅图。

首先可以根据相似三角形知道b的长度,同时圆心与点的方向也知道。 那么 圆心+b 就是  切点连线 与 点与圆心 连线的交点了。 

然后根据 面积,有 l·r = (b的长度)*(中间点到切点的长度) .

就很容易得到切点了。详细看代码,poj返回vector好像会RE,就改成pair了。

  1 #include <cstdio>
  2 #include <cmath>
  3 #include <algorithm>
  4 #include <vector>
  5 #include <map>
  6 #include <cstring>
  7 using namespace std;
  8 typedef double db;
  9 const db eps = 1e-7;
 10 const db pi = acos(-1);
 11 int sign(db k){
 12     if (k>eps) return 1; else if (k<-eps) return -1; return 0;
 13 }
 14 int cmp(db k1,db k2){return sign(k1-k2);}
 15 struct point{
 16     db x,y;
 17     point operator + (const point &k1) const{return (point){k1.x+x,k1.y+y};}
 18     point operator - (const point &k1) const{return (point){x-k1.x,y-k1.y};}
 19     point operator * (db k1) const{return (point){x*k1,y*k1};}
 20     point operator / (db k1) const{return (point){x/k1,y/k1};}
 21     point turn(db k1){ return (point){x*cos(k1)-y*sin(k1),x*sin(k1)+y*cos(k1)};}
 22     point turn90(){ return (point){-y,x};}
 23     db abs(){ return sqrt(x*x+y*y);}
 24     db abs2(){ return x*x+y*y;}
 25     db dis(point k1){ return (*this-k1).abs();}
 26     point unit(){db w=abs(); return (point){x/w,y/w};}
 27 };
 28 db cross(point k1,point k2){ return k1.x*k2.y-k1.y*k2.x;}
 29 db dot(point k1,point k2){ return k1.x*k2.x+k1.y*k2.y;}
 30 point proj(point k1,point k2,point q){
 31     point k=k2-k1;
 32     return k1+k*(dot(q-k1,k)/k.abs2());
 33 }
 34 point getLL(point k1,point k2,point k3,point k4){
 35     db w1=cross(k1-k3,k4-k3),w2=cross(k4-k3,k2-k3);
 36     return (k1*w2+k2*w1)/(w1+w2);
 37 }
 38 struct circle{
 39     point o;db r;
 40     int inside(point k){ return cmp(r,o.dis(k));}
 41 };
 42 pair<point,point> TangentCP(circle k1,point k2){//
 43     db a=(k2-k1.o).abs(),b=k1.r*k1.r/a,c=sqrt(max((db)0.0,k1.r*k1.r-b*b));
 44     point k=(k2-k1.o).unit(),m=k1.o+k*b,del=k.turn90()*c;
 45     return {m-del,m+del};
 46 }
 47 struct line{
 48     db l,r;
 49 };
 50 bool cmp2(line a,line b){
 51     return a.l<b.l;
 52 }
 53 int n;
 54 line l[1551];
 55 circle c[1551];
 56 pair<point,point> g;
 57 point e,s1,s2;
 58 int main(){
 59     bool f=0;
 60     while (scanf("%d",&n)&&n){
 61         if(f)printf("
");
 62         f=1;
 63         scanf("%lf%lf",&e.x,&e.y);
 64         for(int i=1;i<=n;i++){
 65             scanf("%lf%lf%lf",&c[i].o.x,&c[i].o.y,&c[i].r);
 66         }
 67         for(int i=1;i<=n;i++){
 68             g=TangentCP(c[i],e);
 69             s1 = getLL(e,g.first,point{0.0,0.0},point{100.0,0.0});
 70             s2 = getLL(e,g.second,point{0.0,0.0},point{100.0,0.0});
 71             l[i]=line{s2.x,s1.x};
 72         }
 73         sort(l+1,l+1+n,cmp2);
 74         db L = l[1].l,R = l[1].r;
 75         for(int i=2;i<=n;i++){
 76             if(l[i].l>R){
 77                 printf("%.2f %.2f
",L,R);
 78                 L = l[i].l,R=l[i].r;
 79             } else
 80                 R = max(R,l[i].r);
 81         }
 82         printf("%.2f %.2f
",L,R);
 83     }
 84 }
 85 /**
 86  *
 87 1
 88 300 300
 89 390 150 90
 90 0
 91 
 92 6
 93 300 450
 94 70 50 30
 95 120 20 20
 96 270 40 10
 97 250 85 20
 98 220 30 30
 99 380 100 100
100  */
View Code
原文地址:https://www.cnblogs.com/MXang/p/10553423.html