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 }
没有人能阻止我前进的步伐,除了我自己!