HDU5130 Signal Interference

  1 /*
  2  HDU5130 Signal Interference
  3  http://acm.hdu.edu.cn/showproblem.php?pid=5130
  4  计算几何 圆与多边形面积交
  5  *
  6  */
  7 
  8 
  9 #include <cstdio>
 10 #include <algorithm>
 11 #include <cmath>
 12 using namespace std;
 13 const double Pi=acos(-1.0);
 14 const double eps = 1e-8;
 15 const int Nmax=1005;
 16 double k;
 17 int sgn(double x)
 18 { 
 19     if(x<-eps)
 20         return -1;
 21     if(x>eps)
 22         return 1;
 23     return 0;
 24 }
 25 double Abs(double x)
 26 {
 27     if(sgn(x)<0)
 28         x=-x;
 29     else if(sgn(x)==0)
 30         x=0.0;
 31     return x;
 32 }
 33 double sqr(double x)
 34 {
 35     return x*x;
 36 }
 37 double Sqrt(double x) 
 38 { 
 39     return max(0.0,sqrt(x)); 
 40 }
 41 struct Pt 
 42 {
 43     double x,y;
 44     Pt() { }
 45     Pt(double x, double y) : x(x), y(y) { }
 46     
 47     Pt operator - (const Pt &b)
 48     {
 49         return Pt(x-b.x,y-b.y);
 50     }
 51     Pt operator + (const Pt &b)
 52     {
 53         return Pt(x+b.x,y+b.y);
 54     }
 55     friend Pt operator * (double a,Pt p)
 56     {
 57         return Pt(p.x*a,p.y*a);
 58     }
 59     friend Pt operator * (Pt p,double a)
 60     {
 61         return Pt(p.x*a,p.y*a);
 62     }
 63     friend Pt operator / (Pt p,double a)
 64     {
 65         return Pt(p.x/a,p.y/a);
 66     }
 67     double norm()
 68     { 
 69         return Sqrt(x*x + y*y); 
 70     }
 71     double len()
 72     {
 73         return norm();
 74     }
 75     void print() 
 76     { 
 77         printf("(%f, %f)\n", x, y); 
 78     }
 79 };
 80 int n;
 81 Pt pl[Nmax];
 82 Pt pr,A,B,p0,p1;
 83 double dist (Pt a, Pt b) 
 84 {    
 85     return (a-b).norm(); 
 86 }
 87 double dot(Pt a,Pt b)//点乘 
 88 {
 89     return a.x*b.x+a.y*b.y; 
 90 }
 91 double det(Pt a,Pt b)
 92 {
 93     return a.x*b.y-a.y*b.x;
 94 }
 95 Pt rotate(Pt p,double a)//P点绕原点逆时针旋转a弧度
 96 {
 97     return Pt(p.x*cos(a)-p.y*sin(a),p.x*sin(a)+p.y*cos(a));
 98 }
 99 struct Sg//线段 
100 {
101     Pt s, t;
102     Sg() { }
103     Sg(Pt s, Pt t) : s(s), t(t) { }
104     Sg(double a, double b, double c, double d) : s(a, b), t(c, d) { }
105 };
106 bool PtOnSegment(Pt p, Pt a, Pt b) //p是否在线段ab上,把<=改成<就能实现不含线段端点的点在线段上的判断。
107 {
108     return !sgn(det(p-a, b-a)) && sgn(dot(p-a, p-b)) <= 0;
109 }
110 bool PtOnLine(Pt p, Pt a, Pt b) //p是否在直线ab上
111 {
112     return !sgn(det(p-a, b-a));
113 }
114 Pt PtLineProj(Pt s, Pt t, Pt p) //p到直线st的投影
115 {
116     double r = dot(p-s, t-s) / (t - s).norm();
117     return s + (t - s) * r;
118 }
119 bool parallel(Pt a, Pt b, Pt s, Pt t) 
120 {
121     return !sgn(det(a-b, s-t));
122 }
123 Pt triangleMassCenter(Pt a, Pt b, Pt c) 
124 {
125     return (a+b+c) / 3.0;
126 }
127 double polygon_area(Pt poly[],int n)
128 {
129     double ans=0.0;
130     if(n<3)
131         return ans;
132     for(int i=1;i<=n;i++)
133         ans+=det(poly[i],poly[i%n+1]);
134     return ans*0.5;
135 }
136 
137 struct Circle
138 {
139     Pt c;
140     double r;
141     Circle(Pt _c,double _r)
142     {
143         c=_c;
144         r=_r;
145     }
146 };
147 bool PointInCircle(Circle a,Pt p)
148 {
149     Pt c=a.c;
150     return sgn( (p-c).norm()-a.r )<0;
151 }
152 
153 bool PointOnCircle(Circle a,Pt p)
154 {
155     Pt c=a.c;
156     return sgn( (p-c).norm()-a.r )==0;
157 }
158 
159 bool PointIOCircle(Circle a,Pt p)
160 {
161     Pt c=a.c;
162     return sgn( (p-c).norm()-a.r )<=0;
163 }
164 
165 void circle_cross_line(Circle c,Pt a, Pt b, Pt ans[], int &num)
166 {
167     double x1=a.x,y1=a.y,x2=b.x,y2=b.y;
168     double dx=x2-x1,dy=y2-y1;
169     double tmpx=x1-c.c.x,tmpy=y1-c.c.y;
170     double A=dx*dx+dy*dy;
171     double B=2.0*( dx*tmpx+dy*tmpy );
172     double C=tmpx*tmpx+tmpy*tmpy-c.r*c.r;
173     double delta=B*B-4.0*A*C;
174     num=0;
175     if(sgn(delta)<0)
176         return;
177     double t1=(-B-Sqrt(delta))/(2.0*A);
178     double t2=(-B+Sqrt(delta))/(2.0*A);
179     if(sgn(t1-1.0)<=0 && sgn(t1)>=0)
180         ans[++num]=Pt(x1+t1*dx,y1+t1*dy);
181     if(sgn(delta)==0)
182         return;
183     if(sgn(t2-1.0)<=0 && sgn(t2)>=0)
184         ans[++num]=Pt(x1+t2*dx,y1+t2*dy);
185 }   
186 
187 double sector_area(Circle c,Pt a,Pt b)
188 {
189     a=a-c.c,b=b-c.c;
190     double theta = atan2(a.y, a.x) - atan2(b.y, b.x);
191     while (sgn(theta) <= 0) theta += 2.0*Pi;
192     while (sgn(theta-2.0*Pi)>0) theta -= 2.0*Pi;
193     theta = min(theta, 2.0*Pi - theta);
194     return c.r*c.r*theta*0.5;
195 }
196 
197 double CirclePolyArea(Circle c,Pt poly[],int n)
198 {
199     double ans=0.0;
200     Pt p[3];
201     int num;
202     for(int i=1;i<=n;i++)
203     {
204         Pt a=poly[i],b=poly[i%n+1];
205         int ina=PointInCircle(c,a);
206         int inb=PointInCircle(c,b);
207         Pt da=a-c.c,db=b-c.c;
208         int s=sgn(det(da,db));
209         double part=0.0;
210         if(ina)
211         {
212             if(inb)
213             {
214                 part=Abs(det(da,db))*0.5;
215             }
216             else
217             {
218                 circle_cross_line(c,a,b,p,num);
219                 part=sector_area(c,p[1],b)+Abs(det(da,p[1]-c.c))*0.5;
220             }
221         }
222         else
223         {
224             if(inb)
225             {
226                 circle_cross_line(c,a,b,p,num);
227                 part=sector_area(c,p[1],a)+Abs(det(db,p[1]-c.c))*0.5;
228             }
229             else
230             {
231                 circle_cross_line(c,a,b,p,num);
232                 if(num==2)
233                 {
234                     part=sector_area(c,a,p[1])+sector_area(c,b,p[2])+Abs(det(p[1]-c.c,p[2]-c.c))*0.5;
235                 }
236                 else
237                 {
238                     part=sector_area(c,a,b);
239                 }
240             }
241         }
242         if(s!=0)
243             ans+=1.0*s*part;
244     }
245     return ans;
246 }
247 int main()
248 {
249    int t=0;
250     while(scanf("%d%lf",&n,&k)==2)
251     {
252         t++;
253         for(int i=1;i<=n;i++)
254             scanf("%lf%lf",&pl[i].x,&pl[i].y);
255         scanf("%lf%lf%lf%lf",&A.x,&A.y,&B.x,&B.y);
256         double r;
257         double E=(2.0*B.x-2.0*sqr(k)*A.x)/(1.0-sqr(k));  
258         double F=(2.0*B.y-2.0*sqr(k)*A.y)/(1.0-sqr(k));  
259         double G=(sqr(k*A.x)+sqr(k*A.y)-sqr(B.x)-sqr(B.y))/(1.0-sqr(k));  
260         pr.x=E/2.0,pr.y=F/2.0;  
261         r=Sqrt(G+sqr(E)/4.0+sqr(F)/4.0);  
262         Circle C(pr,r);
263         double ans=Abs( CirclePolyArea(C,pl,n) );
264         printf("Case %d: ",t);
265         printf("%.10f\n",ans+eps);
266     }
267     return 0;
268 }

 

posted @ 2017-03-27 00:08  BBBob  阅读(333)  评论(0编辑  收藏  举报