POJ 1375 圆的切线

题意:

求从光源透过圆形的阴影的线段,并排序输出。

 

题解:

求圆的切线,利用勾股定理和坐标旋转即可。

处理出所有与地平线的交点,标号正负1,排序,然后扫一遍就好了~

 

View Code
  1 #include <iostream>

  2 #include <cstring>

  3 #include <cstdio>

  4 #include <cstdlib>

  5 #include <algorithm>

  6 #include <cmath>

  7 

  8 #define N 2222

  9 #define BUG system("pause")

 10 

 11 using namespace std;

 12 

 13 struct PO

 14 {

 15     double x,y,r;

 16     int fg;

 17     void prt() {printf("%lf    %lf\n",x,y);}

 18 }p[N],s;

 19 

 20 struct FP

 21 {

 22     double x;

 23     int fg;

 24 }fp[N];

 25 

 26 struct LI

 27 {

 28     PO a,b;

 29     int fg;

 30 }li[N],flr;

 31 

 32 int n,cnt,gs;

 33 double lt;

 34 

 35 inline PO operator +(PO a,PO b)

 36 {

 37     PO as;

 38     as.x=a.x+b.x; as.y=a.y+b.y;

 39     return as;

 40 }

 41 

 42 inline PO operator -(PO a,PO b)

 43 {

 44     PO as;

 45     as.x=a.x-b.x; as.y=a.y-b.y;

 46     return as;

 47 }

 48 

 49 inline PO operator /(PO a,double k)

 50 {

 51     a.x/=k; a.y/=k;

 52     return a;

 53 }

 54 

 55 inline PO operator *(PO a,double k)

 56 {

 57     a.x*=k; a.y*=k;

 58     return a;

 59 }

 60 

 61 inline void read()

 62 {

 63     scanf("%lf%lf",&s.x,&s.y);

 64     for(int i=1;i<=n;i++) scanf("%lf%lf%lf",&p[i].x,&p[i].y,&p[i].r);

 65 }

 66 

 67 inline PO rotate(PO a,double sss,double ccc)

 68 {

 69     PO ans;

 70     ans.x=a.x*ccc-a.y*sss;

 71     ans.y=a.x*sss+a.y*ccc;

 72     return ans;

 73 }

 74 

 75 inline double getdis(PO &a,PO &b)

 76 {

 77     return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

 78 }

 79 

 80 inline void getli(PO &s,PO &c,PO &a,PO &b)

 81 {

 82     double sc=getdis(s,c);

 83     double sp=sqrt(sc*sc-c.r*c.r);

 84     double sss=c.r/sc;

 85     double ccc=sp/sc;

 86     PO len=(c-s)*sp/sc;

 87     a=s+rotate(len,sss,ccc);

 88     b=s+rotate(len,-sss,ccc);

 89 }

 90 

 91 inline double cross(PO &a,PO &b,PO &c)

 92 {

 93     return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y);

 94 }

 95 

 96 inline PO getpoint(PO &a,PO &b,PO &c,PO &d)

 97 {

 98     double k1=cross(a,d,c),k2=cross(b,c,d);

 99     PO res=b-a;

100     res=a+res*k1/(k1+k2);

101     return res;

102 }

103 

104 inline bool cmp(const FP &a,const FP &b)

105 {

106     return a.x<b.x;

107 }

108 

109 inline void go()

110 {

111     cnt=gs=0;PO a,b;

112     for(int i=1;i<=n;i++)

113     {

114         getli(s,p[i],a,b);

115         if(a.x>b.x) swap(a,b);

116         li[++cnt].a=s; li[cnt].b=a; li[cnt].fg=1;

117         li[++cnt].a=s; li[cnt].b=b; li[cnt].fg=-1;

118     }

119     flr.a.x=flr.a.y=flr.b.y=0; flr.b.x=1;

120     for(int i=1;i<=cnt;i++)

121     {

122         PO tmp=getpoint(flr.a,flr.b,li[i].a,li[i].b);

123         fp[i].x=tmp.x;

124         fp[i].fg=li[i].fg;

125     }

126     sort(fp+1,fp+1+cnt,cmp);

127     for(int i=1;i<=cnt;i++)

128     {

129         gs+=fp[i].fg;

130         if(gs==1&&fp[i].fg==1) lt=fp[i].x;//注意缺一不可! 

131         else if(gs==0) printf("%.2lf %.2lf\n",lt,fp[i].x);

132     }

133     puts("");

134 }

135 

136 int main()

137 {

138     while(scanf("%d",&n),n) read(),go();

139     return 0;

140 }

 

 

你可能感兴趣的:(poj)