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 }

 

 

posted @ 2013-02-28 23:32  proverbs  阅读(244)  评论(0编辑  收藏  举报