Harry Potter and J.K.Rowling(半平面交+圆和矩形交)

Harry Potter and J.K.Rowling

http://acm.hdu.edu.cn/showproblem.php?pid=3982

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1094    Accepted Submission(s): 357


Problem Description
In July 31st, last month, the author of the famous novel series J.K.Rowling celebrated her 46th birthday. Many friends gave their best wishes. They gathered together and shared one large beautiful cake.
Rowling had lots of friends, and she had a knife to cut the cake into many pieces. On the cake there was a cherry. After several cuts, the piece with the cherry was left for Rowling. Before she enjoyed it, she wondered how large this piece was, i.e., she wondered how much percentage of the cake the piece with the only cherry has.
 

 

Input
First line has an integer T, indicating the number of test cases.
T test cases follow. The first line of each test case has one number r (1 <= r <= 10000) and one integer n (0 <= n <= 2000), indicating the radius of the cake and the number of knife cuts. n lines follow. The i-th line has four numbers, x1, y1, x2, y2. (x1, y1) and (x2, y2) are two points on the i-th cut. (-10000 <= x1, y1, x2, y2 <= 10000) The last line of each case has two number x, y, indicating the coordinate(x, y) of the cherry.

Technical Specification

1. R, x1, y2, x2, y2, x, y all have two digits below decimal points.
2. The center of the cake is always on the point (0, 0).
3. The cherry was always on the cake and would not be on the knife cuts.
 

 

Output
For each test case, in one line output the case number and the percentage the piece with the cherry has of whole original cake, rounded to five fractional digits.
 

 

Sample Input
1
1.00 2
-1.00 0.00 1.00 0.00
0.00 -1.00 0.00 1.00
0.50 0.50
 

 

Sample Output
Case 1: 25.00000%

 

 

附上测试数据,半平面交模板题

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cstring>
  4 #include<algorithm>
  5 #include<cmath>
  6 using namespace std;
  7 const double eps=1e-8;
  8 const double INF=1e20;
  9 const double PI=acos(-1.0);
 10 const int maxp=1010;
 11 int sgn(double x){
 12     if(fabs(x)<eps) return 0;
 13     if(x<0) return -1;
 14     else return 1;
 15 }
 16 inline double sqr(double x){return x*x;}
 17 struct Point{
 18     double x,y;
 19     Point(){}
 20     Point(double _x,double _y){
 21         x=_x;
 22         y=_y;
 23     }
 24     void input(){
 25         scanf("%lf %lf",&x,&y);
 26     }
 27     void output(){
 28         printf("%.2f %.2f\n",x,y);
 29     }
 30     bool operator == (const Point &b)const{
 31         return sgn(x-b.x) == 0 && sgn(y-b.y)== 0;
 32     }
 33     bool operator < (const Point &b)const{
 34         return sgn(x-b.x)==0?sgn(y-b.y)<0:x<b.x;
 35     }
 36     Point operator - (const Point &b)const{
 37         return Point(x-b.x,y-b.y);
 38     }
 39     //叉积
 40     double operator ^ (const Point &b)const{
 41         return x*b.y-y*b.x;
 42     }
 43     //点积
 44     double operator * (const Point &b)const{
 45         return x*b.x+y*b.y;
 46     }
 47     //返回长度
 48     double len(){
 49         return hypot(x,y);
 50     }
 51     //返回长度的平方
 52     double len2(){
 53         return x*x+y*y;
 54     }
 55     //返回两点的距离
 56     double distance(Point p){
 57         return hypot(x-p.x,y-p.y);
 58     }
 59     Point operator + (const Point &b)const{
 60         return Point(x+b.x,y+b.y);
 61     }
 62     Point operator * (const double &k)const{
 63         return Point(x*k,y*k);
 64     }
 65     Point operator / (const double &k)const{
 66         return Point(x/k,y/k);
 67     }
 68 
 69     //计算pa和pb的夹角
 70     //就是求这个点看a,b所成的夹角
 71     ///LightOJ1202
 72     double rad(Point a,Point b){
 73         Point p=*this;
 74         return fabs(atan2(fabs((a-p)^(b-p)),(a-p)*(b-p)));
 75     }
 76     //化为长度为r的向量
 77     Point trunc(double r){
 78         double l=len();
 79         if(!sgn(l)) return *this;
 80         r/=l;
 81         return Point(x*r,y*r);
 82     }
 83     //逆时针转90度
 84     Point rotleft(){
 85         return Point(-y,x);
 86     }
 87     //顺时针转90度
 88     Point rotright(){
 89         return Point(y,-x);
 90     }
 91     //绕着p点逆时针旋转angle
 92     Point rotate(Point p,double angle){
 93         Point v=(*this) -p;
 94         double c=cos(angle),s=sin(angle);
 95         return Point(p.x+v.x*c-v.y*s,p.y+v.x*s+v.y*c);
 96     }
 97 };
 98 
 99 struct Line{
100     Point s,e;
101     Line(){}
102     Line(Point _s,Point _e){
103         s=_s;
104         e=_e;
105     }
106     bool operator==(Line v){
107         return (s==v.s)&&(e==v.e);
108     }
109     //根据一个点和倾斜角angle确定直线,0<=angle<pi
110     Line(Point p,double angle){
111         s=p;
112         if(sgn(angle-PI/2)==0){
113             e=(s+Point(0,1));
114         }
115         else{
116             e=(s+Point(1,tan(angle)));
117         }
118     }
119     //ax+by+c=0;
120     Line(double a,double b,double c){
121         if(sgn(a)==0){
122             s=Point(0,-c/b);
123             e=Point(1,-c/b);
124         }
125         else if(sgn(b)==0){
126             s=Point(-c/a,0);
127             e=Point(-c/a,1);
128         }
129         else{
130             s=Point(0,-c/b);
131             e=Point(1,(-c-a)/b);
132         }
133     }
134     void input(){
135         s.input();
136         e.input();
137     }
138     void adjust(){
139         if(e<s) swap(s,e);
140     }
141     //求线段长度
142     double length(){
143         return s.distance(e);
144     }
145     //返回直线倾斜角 0<=angle<pi
146     double angle(){
147         double k=atan2(e.y-s.y,e.x-s.x);
148         if(sgn(k)<0) k+=PI;
149         if(sgn(k-PI)==0) k-=PI;
150         return k;
151     }
152     //点和直线的关系
153     //1 在左侧
154     //2 在右侧
155     //3 在直线上
156     int relation(Point p){
157         int c=sgn((p-s)^(e-s));
158         if(c<0) return 1;
159         else if(c>0) return 2;
160         else return 3;
161     }
162     //点在线段上的判断
163     bool pointonseg(Point p){
164         return sgn((p-s)^(e-s))==0&&sgn((p-s)*(p-e))<=0;
165     }
166     //两向量平行(对应直线平行或重合)
167     bool parallel(Line v){
168         return sgn((e-s)^(v.e-v.s))==0;
169     }
170     //两线段相交判断
171     //2 规范相交
172     //1 非规范相交
173     //0 不相交
174     int segcrossseg(Line v){
175         int d1=sgn((e-s)^(v.s-s));
176         int d2=sgn((e-s)^(v.e-s));
177         int d3=sgn((v.e-v.s)^(s-v.s));
178         int d4=sgn((v.e-v.s)^(e-v.s));
179         if((d1^d2)==-2&&(d3^d4)==-2) return 2;
180         return (d1==0&&sgn((v.s-s)*(v.s-e))<=0||
181                 d2==0&&sgn((v.e-s)*(v.e-e))<=0||
182                 d3==0&&sgn((s-v.s)*(s-v.e))<=0||
183                 d4==0&&sgn((e-v.s)*(e-v.e))<=0);
184     }
185     //直线和线段相交判断
186     //-*this line -v seg
187     //2 规范相交
188     //1 非规范相交
189     //0 不相交
190     int linecrossseg(Line v){
191         int d1=sgn((e-s)^(v.s-s));
192         int d2=sgn((e-s)^(v.e-s));
193         if((d1^d2)==-2) return 2;
194         return (d1==0||d2==0);
195     }
196     //两直线关系
197     //0 平行
198     //1 重合
199     //2 相交
200     int linecrossline(Line v){
201         if((*this).parallel(v))
202             return v.relation(s)==3;
203         return 2;
204     }
205     //求两直线的交点
206     //要保证两直线不平行或重合
207     Point crosspoint(Line v){
208         double a1=(v.e-v.s)^(s-v.s);
209         double a2=(v.e-v.s)^(e-v.s);
210         return Point((s.x*a2-e.x*a1)/(a2-a1),(s.y*a2-e.y*a1)/(a2-a1));
211     }
212     //点到直线的距离
213     double dispointtoline(Point p){
214         return fabs((p-s)^(e-s))/length();
215     }
216     //点到线段的距离
217     double dispointtoseg(Point p){
218         if(sgn((p-s)*(e-s))<0||sgn((p-e)*(s-e))<0)
219             return min(p.distance(s),p.distance(e));
220         return dispointtoline(p);
221     }
222     //返回线段到线段的距离
223     //前提是两线段不相交,相交距离就是0了
224     double dissegtoseg(Line v){
225         return min(min(dispointtoseg(v.s),dispointtoseg(v.e)),min(v.dispointtoseg(s),v.dispointtoseg(e)));
226     }
227     //返回点P在直线上的投影
228     Point lineprog(Point p){
229         return s+(((e-s)*((e-s)*(p-s)))/((e-s).len2()));
230     }
231     //返回点P关于直线的对称点
232     Point symmetrypoint(Point p){
233         Point q=lineprog(p);
234         return Point(2*q.x-p.x,2*q.y-p.y);
235     }
236 };
237 
238 struct circle{
239     Point p;
240     double r;
241     circle(){}
242     circle(Point _p,double _r){
243         p=_p;
244         r=_r;
245     }
246 
247     circle(double x,double y,double _r){
248         p=Point(x,y);
249         r=_r;
250     }
251 
252     circle(Point a,Point b,Point c){///三角形的外接圆
253         Line u=Line((a+b)/2,((a+b)/2)+((b-a).rotleft()));
254         Line v=Line((b+c)/2,((b+c)/2)+((c-b).rotleft()));
255         p=u.crosspoint(v);
256         r=p.distance(a);
257     }
258 
259     circle(Point a,Point b,Point c,bool t){///三角形的内切圆
260         Line u,v;
261         double m=atan2(b.y-a.y,b.x-a.x),n=atan2(c.y-a.y,c.x-a.x);
262         u.s=a;
263         u.e=u.s+Point(cos((n+m)/2),sin((n+m)/2));
264         v.s=b;
265         m=atan2(a.y-b.y,a.x-b.x),n=atan2(c.y-b.y,c.x-b.x);
266         v.e=v.s+Point(cos((n+m)/2),sin((n+m)/2));
267         p=u.crosspoint(v);
268         r=Line(a,b).dispointtoseg(p);
269     }
270 
271     void input(){
272         p.input();
273         scanf("%lf",&r);
274     }
275 
276     void output(){
277         printf("%.2f %.2f %.2f\n",p.x,p.y,r);
278     }
279 
280     bool operator==(circle v){
281         return (p==v.p)&&sgn(r-v.r)==0;
282     }
283 
284     bool operator<(circle v)const{
285         return ((p<v.p)||((p==v.p)&&sgn(r-v.r)<0));
286     }
287 
288     double area(){
289         return PI*r*r;
290     }
291 
292     double circumference(){ ///周长
293         return 2*PI*r;
294     }
295 
296     int relation(Point b){///点和圆的关系  0圆外  1圆上  2圆内
297         double dst=b.distance(p);
298         if(sgn(dst-r)<0) return 2;
299         else if(sgn(dst-r)==0) return 1;
300         return 0;
301     }
302 
303     int relationseg(Line v){///线段和圆的关系,比较的是圆心到线段的距离和半径的关系
304         double dst=v.dispointtoseg(p);
305         if(sgn(dst-r)<0) return 2;
306         else if(sgn(dst-r)==0) return 1;
307         return 0;
308     }
309 
310     int relationline(Line v){///直线和圆的关系,比较的是圆心到直线的距离和半径的关系
311         double dst=v.dispointtoline(p);
312         if(sgn(dst-r)<0) return 2;
313         else if(sgn(dst-r)==0) return 1;
314         return 0;
315     }
316 
317     int relationcircle(circle v){///两圆的关系  5相离 4外切 3相交 2内切 1内含
318         double d=p.distance(v.p);
319         if(sgn(d-r-v.r)>0) return 5;
320         if(sgn(d-r-v.r)==0) return 4;
321         double l=fabs(r-v.r);
322         if(sgn(d-r-v.r)<0&&sgn(d-l)>0) return 3;
323         if(sgn(d-l)==0) return 2;
324         if(sgn(d-l)<0)  return 1;
325     }
326 
327     int pointcrosscircle(circle v,Point &p1,Point &p2){///求两个圆的交点,0没有交点 1一个交点 2两个交点
328         int rel=relationcircle(v);
329         if(rel == 1 || rel == 5) return 0;
330         double d=p.distance(v.p);
331         double l=(d*d+r*r-v.r*v.r)/2*d;
332         double h=sqrt(r*r-l*l);
333         Point tmp=p+(v.p-p).trunc(l);
334         p1=tmp+((v.p-p).rotleft().trunc(h));
335         p2=tmp+((v.p-p).rotright().trunc(h));
336         if(rel == 2 || rel == 4) return 1;
337         return 2;
338     }
339 
340     int pointcrossline(Line v,Point &p1,Point &p2){///求直线和圆的交点,返回交点的个数
341         if(!(*this).relationline(v)) return 0;
342         Point a=v.lineprog(p);
343         double d=v.dispointtoline(p);
344         d=sqrt(r*r-d*d);
345         if(sgn(d)==0) {
346             p1=a;
347             p2=a;
348             return 1;
349         }
350         p1=a+(v.e-v.s).trunc(d);
351         p2=a-(v.e-v.s).trunc(d);
352         return 2;
353     }
354 
355     int getcircle(Point a,Point b,double r1,circle &c1,circle &c2){///得到过a,b两点,半径为r1的两个圆
356         circle x(a,r1),y(b,r1);
357         int t=x.pointcrosscircle(y,c1.p,c2.p);
358         if(!t) return 0;
359         c1.r=c2.r=r;
360         return t;
361     }
362 
363     int getcircle(Line u,Point q,double r1,circle &c1,circle &c2){///得到与直线u相切,过点q,半径为r1的圆
364         double dis = u.dispointtoline(q);
365         if(sgn(dis-r1*2)>0) return 0;
366         if(sgn(dis)==0) {
367             c1.p=q+((u.e-u.s).rotleft().trunc(r1));
368             c2.p=q+((u.e-u.s).rotright().trunc(r1));
369             c1.r=c2.r=r1;
370             return 2;
371         }
372         Line u1=Line((u.s+(u.e-u.s).rotleft().trunc(r1)),(u.e+(u.e-u.s).rotleft().trunc(r1)));
373         Line u2=Line((u.s+(u.e-u.s).rotright().trunc(r1)),(u.e+(u.e-u.s).rotright().trunc(r1)));
374         circle cc=circle(q,r1);
375         Point p1,p2;
376         if(!cc.pointcrossline(u1,p1,p2)) cc.pointcrossline(u2,p1,p2);
377         c1=circle(p1,r1);
378         if(p1==p2){
379             c2=c1;
380             return 1;
381         }
382         c2=circle(p2,r1);
383         return 2;
384     }
385 
386     int getcircle(Line u,Line v,double r1,circle &c1,circle &c2,circle &c3,circle &c4){///同时与直线u,v相切,半径为r1的圆
387         if(u.parallel(v)) return 0;///两直线平行
388         Line u1=Line(u.s+(u.e-u.s).rotleft().trunc(r1),u.e+(u.e-u.s).rotleft().trunc(r1));
389         Line u2=Line(u.s+(u.e-u.s).rotright().trunc(r1),u.e+(u.e-u.s).rotright().trunc(r1));
390         Line v1=Line(v.s+(v.e-v.s).rotleft().trunc(r1),v.e+(v.e-v.s).rotleft().trunc(r1));
391         Line v2=Line(v.s+(v.e-v.s).rotright().trunc(r1),v.e+(v.e-v.s).rotright().trunc(r1));
392         c1.r=c2.r=c3.r=c4.r=r1;
393         c1.p=u1.crosspoint(v1);
394         c2.p=u1.crosspoint(v2);
395         c3.p=u2.crosspoint(v1);
396         c4.p=u2.crosspoint(v2);
397         return 4;
398     }
399 
400     int getcircle(circle cx,circle cy,double r1,circle &c1,circle &c2){///同时与不相交圆 cx,cy相切,半径为r1的圆
401         circle x(cx.p,r1+cx.r),y(cy.p,r1+cy.r);
402         int t=x.pointcrosscircle(y,c1.p,c2.p);
403         if(!t) return 0;
404         c1.r=c2.r=r1;
405         return t;
406     }
407 
408     int tangentline(Point q,Line &u,Line &v){///过一点作圆的切线(先判断点和圆的关系)
409         int x=relation(q);
410         if(x==2) return 0;
411         if(x==1){
412             u=Line(q,q+(q-p).rotleft());
413             v=u;
414             return 1;
415         }
416         double d=p.distance(q);
417         double l=r*r/d;
418         double h=sqrt(r*r-l*l);
419         u=Line(q,p+((q-p).trunc(l)+(q-p).rotleft().trunc(h)));
420         v=Line(q,p+((q-p).trunc(l)+(q-p).rotright().trunc(h)));
421         return 2;
422     }
423 
424     double areacircle(circle v){///求两圆相交的面积
425         int rel=relationcircle(v);
426         if(rel >= 4) return 0.0;
427         if(rel <= 2) return min(area(),v.area());
428         double d=p.distance(v.p);
429         double hf=(r+v.r+d)/2.0;
430         double ss=2*sqrt(hf*(hf-r)*(hf-v.r)*(hf-d));
431         double a1=acos((r*r+d*d-v.r*v.r)/(2.0*r*d));
432         a1=a1*r*r;
433         double a2=acos((v.r*v.r+d*d-r*r)/(2.0*v.r*d));
434         a2=a2*v.r*v.r;
435         return a1+a2-ss;
436     }
437 
438     double areatriangle(Point a,Point b){///求圆和三角形pab的相交面积
439         if(sgn((p-a)^(p-b))==0) return 0.0;
440         Point q[5];
441         int len=0;
442         q[len++]=a;
443         Line l(a,b);
444         Point p1,p2;
445         if(pointcrossline(l,q[1],q[2])==2){
446             if(sgn((a-q[1])*(b-q[1]))<0) q[len++]=q[1];
447             if(sgn((a-q[2])*(b-q[2]))<0) q[len++]=q[2];
448         }
449         q[len++]=b;
450         if(len==4 && sgn((q[0]-q[1])*(q[2]-q[1]))>0) swap(q[1],q[2]);
451         double res=0;
452         for(int i=0;i<len-1;i++){
453             if(relation(q[i])==0||relation(q[i+1])==0){
454                 double arg=p.rad(q[i],q[i+1]);
455                 res+=r*r*arg/2.0;
456             }
457             else{
458                 res+=fabs((q[i]-p)^(q[i+1]-p))/2.0;
459             }
460         }
461         return res;
462     }
463 };
464 
465 struct polygon{
466     int n;
467     Point p[1010];
468     Line l[1010];
469     void input(int _n){
470         n=_n;
471         for(int i=0;i<n;i++){
472             p[i].input();
473         }
474     }
475 
476     void add(Point q){
477         p[n++]=q;
478     }
479 
480     void getline(){
481         for(int i=0;i<n;i++){
482             l[i]=Line(p[i],p[(i+1)%n]);
483         }
484     }
485 
486     struct cmp{
487         Point p;
488         cmp(const Point &p0){p=p0;}
489         bool operator()(const Point &aa,const Point &bb){
490             Point a=aa,b=bb;
491             int d=sgn((a-p)^(b-p));
492             if(d==0){
493                 return sgn(a.distance(p)-b.distance(p))<0;
494             }
495             return d>0;
496         }
497     };
498 
499     void norm(){///进行极角排序
500         Point mi=p[0];
501         for(int i=1;i<n;i++){
502             mi=min(mi,p[i]);
503             sort(p,p+n,cmp(mi));
504         }
505     }
506 
507     void getconvex(polygon &convex){///得到第一种凸包的方法,编号为0~n-1,可能要特判所有点共点或共线的特殊情况
508         sort(p,p+n);
509         convex.n=n;
510         for(int i=0;i<min(n,2);i++){
511             convex.p[i]=p[i];
512         }
513         if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
514         if(n<=2) return;
515         int &top=convex.n;
516         top=1;
517         for(int i=2;i<n;i++){
518             while(top&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<0) top--;
519             convex.p[++top]=p[i];
520         }
521         int temp=top;
522         convex.p[++top]=p[n-2];
523         for(int i=n-3;i>=0;i--){
524             while(top!=temp&&sgn((convex.p[top]-p[i])^(convex.p[top-1]-p[i]))<=0) top--;
525             convex.p[++top]=p[i];
526         }
527         if(convex.n==2&&(convex.p[0]==convex.p[1])) convex.n--;
528         convex.norm();
529     }
530 
531     void Graham(polygon &convex){///得到凸包的第二种方法
532         norm();
533         int &top=convex.n;
534         top=0;
535         if(n==1){
536             top=1;
537             convex.p[0]=p[0];
538             return;
539         }
540         if(n==2){
541             top=2;
542             convex.p[0]=p[0];
543             convex.p[1]=p[1];
544             if(convex.p[0]==convex.p[1]) top--;
545             return;
546         }
547         convex.p[0]=p[0];
548         convex.p[1]=p[1];
549         top=2;
550         for(int i=2;i<n;i++){
551             while(top>1&&sgn((convex.p[top-1]-convex.p[top-2])^(p[i]-convex.p[top-2]))<=0) top--;
552             convex.p[top++]=p[i];
553         }
554         if(convex.n==2 && (convex.p[0]==convex.p[1])) convex.n--;
555     }
556 
557     bool inconvex(){///判断是不是凸的
558         bool s[3];
559         memset(s,false,sizeof(s));
560         for(int i=0;i<n;i++){
561             int j=(i+1)%n;
562             int k=(j+1)%n;
563             s[sgn((p[j]-p[i])^(p[k]-p[i]))+1]=true;
564             if(s[0]&&s[2]) return false;
565         }
566         return true;
567     }
568 
569     int relationpoint(Point q){///判断点和任意多边形的关系  3点上 2边上 1内部 0外部
570         for(int i=0;i<n;i++){
571             if(p[i]==q) return 3;
572         }
573         getline();
574         for(int i=0;i<n;i++){
575             if(l[i].pointonseg(q)) return 2;
576         }
577         int cnt=0;
578         for(int i=0;i<n;i++){
579             int j=(i+1)%n;
580             int k=sgn((q-p[j])^(p[i]-p[j]));
581             int u=sgn(p[i].y-q.y);
582             int v=sgn(p[j].y-q.y);
583             if(k>0&&u<0&&v>=0) cnt++;
584             if(k<0&&v<0&&u>=0) cnt--;
585         }
586         return cnt!=0;
587     }
588 
589     void convexcnt(Line u,polygon &po){///直线u切割凸多边形左侧  注意直线方向
590         int &top=po.n;
591         top=0;
592         for(int i=0;i<n;i++){
593             int d1=sgn((u.e-u.s)^(p[i]-u.s));
594             int d2=sgn((u.e-u.s)^(p[(i+1)%n]-u.s));
595             if(d1>=0) po.p[top++]=p[i];
596             if(d1*d2<0)po.p[top++]=u.crosspoint(Line(p[i],p[(i+1)%n]));
597         }
598     }
599 
600     double getcircumference(){///得到周长
601         double sum=0;
602         for(int i=0;i<n;i++){
603             sum+=p[i].distance(p[(i+1)%n]);
604         }
605         return sum;
606     }
607 
608     double getarea(){///得到面积
609         double sum=0;
610         for(int i=0;i<n;i++){
611             sum+=(p[i]^p[(i+1)%n]);
612         }
613         return fabs(sum)/2;
614     }
615 
616     bool getdir(){///得到方向 1表示逆时针  0表示顺时针
617         double sum=0;
618         for(int i=0;i<n;i++){
619             sum+=(p[i]^p[(i+1)%n]);
620         }
621         if(sgn(sum)>0) return 1;
622         return 0;
623     }
624 
625     Point getbarycentre(){///得到重心
626         Point ret(0,0);
627         double area=0;
628         for(int i=1;i<n-1;i++){
629             double tmp=(p[i]-p[0])^(p[i+1]-p[0]);
630             if(sgn(tmp)==0) continue;
631             area+=tmp;
632             ret.x+=(p[0].x+p[i].x+p[i+1].x)/3*tmp;
633             ret.y+=(p[0].y+p[i].y+p[i+1].y)/3*tmp;
634         }
635         if(sgn(area)) ret =ret/area;
636         return ret;
637     }
638 
639     double areacircle(circle c){///多边形和圆交的面积
640         double ans=0;
641         for(int i=0;i<n;i++){
642             int j=(i+1)%n;
643             if(sgn((p[j]-c.p)^(p[i]-c.p))>=0) ans+=c.areatriangle(p[i],p[j]);
644             else ans-=c.areatriangle(p[i],p[j]);
645         }
646         return fabs(ans);
647     }
648 
649     int relationcircle(circle c){///多边形和圆的关系 2圆完全在多边形内  1圆在多边形里面,碰到了多边形的边界  0其他
650         getline();
651         int x=2;
652         if(relationpoint(c.p)!=1) return 0;
653         for(int i=0;i<n;i++){
654             if(c.relationseg(l[i])==2) return 0;
655             if(c.relationseg(l[i])==1) x=1;
656         }
657         return x;
658     }
659 };
660 
661 double cross(Point a,Point b,Point c){///ab x ac
662     return (b-a)^(c-a);
663 }
664 
665 double dot(Point a,Point b,Point c){///ab*ac;
666     return (b-a)*(c-a);
667 }
668 
669 /*double minRectangleCover(polygon A){///最小矩形面积覆盖  A必须是凸包
670     if(A.n<3) return 0.0;
671     A.p[A.n]==A.p[0];
672     double ans=-1;
673     int r=1,p=1,q;
674     for(int i=0;i<A.n;i++){
675 
676     }
677 }*/
678 
679 vector<Point> convexCut(const vector<Point>&ps,Point q1,Point q2){///直线切凸多边形,多边形是逆时针的,在q1q2的左侧
680     vector<Point>qs;
681     int n=ps.size();
682     for(int i=0;i<n;i++){
683         Point p1=ps[i],p2=ps[(i+1)%n];
684         int d1=sgn((q2-q1)^(p1-q1)),d2=sgn((q2-q1)^(p2-q1));
685         if(d1>=0) qs.push_back(p1);
686         if(d1*d2<0) qs.push_back(Line(p1,p2).crosspoint(Line(q1,q2)));
687     }
688     return qs;
689 }
690 
691 struct halfplane:public Line{
692     double angle;
693     halfplane(){}
694     halfplane(Point _s,Point _e){///表示向量s->e逆时针(左侧)的半平面
695         s=_s;
696         e=_e;
697     }
698     halfplane(Line v){
699         s=v.s;
700         e=v.e;
701     }
702     void calcangle(){
703         angle=atan2(e.y-s.y,e.x-s.x);
704     }
705     bool operator<(const halfplane &b)const{
706         return angle<b.angle;
707     }
708 };
709 
710 struct halfplanes{
711     int n;
712     halfplane hp[2020];
713     Point p[2020];
714     int que[2020];
715     int st,ed;
716     void push(halfplane tmp){
717         hp[n++]=tmp;
718     }
719 
720     void unique(){///去重
721         int m=1;
722         for(int i=1;i<n;i++){
723             if(sgn(hp[i].angle-hp[i-1].angle)!=0) hp[m++]=hp[i];
724             else if(sgn((hp[m-1].e-hp[m-1].s)^(hp[i].s-hp[m-1].s))>0) hp[m-1]=hp[i];
725         }
726         n=m;
727     }
728     bool halfplaneinsert(){
729         for(int i=0;i<n;i++) hp[i].calcangle();
730         sort(hp,hp+n);
731         unique();
732         que[st=0]=0;
733         que[ed=1]=1;
734         p[1]=hp[0].crosspoint(hp[1]);
735         for(int i=2;i<n;i++){
736             while(st<ed&&sgn((hp[i].e-hp[i].s)^(p[ed]-hp[i].s))<0) ed--;
737             while(st<ed&&sgn((hp[i].e-hp[i].s)^(p[st+1]-hp[i].s))<0) st++;
738             que[++ed]=i;
739             if(hp[i].parallel(hp[que[ed-1]])) return false;
740             p[ed]=hp[i].crosspoint(hp[que[ed-1]]);
741         }
742         while(st<ed&&sgn((hp[que[st]].e-hp[que[st]].s)^(p[ed]-hp[que[st]].s))<0) ed--;
743         while(st<ed&&sgn((hp[que[ed]].e-hp[que[ed]].s)^(p[st+1]-hp[que[ed]].s))<0) st++;
744         if(st+1>=ed) return false;
745         return true;
746     }
747 
748     void getconvex(polygon &con){///得到最后半平面交得到的凸多边形,要先调用halfplaneinsert()且返回true
749         p[st]=hp[que[st]].crosspoint(hp[que[ed]]);
750         con.n=ed-st+1;
751         for(int j=st,i=0;j<=ed;i++,j++){
752             con.p[i]=p[j];
753         }
754     }
755 };
756 
757 struct circles{
758     circle c[1010];
759     double ans[1010];///ans[i]表示被覆盖了i次的面积
760     double pre[1010];
761     int n;
762     circles(){}
763     void add(circle cc){
764         c[n++]=cc;
765     }
766 
767     bool inner(circle x,circle y){///x包含在y中
768         if(x.relationcircle(y)!=1) return 0;
769         return sgn(x.r-y.r)<=0?1:0;
770     }
771 
772     void init_or(){///圆的面积并去掉内含的圆
773         bool mark[1010]={0};
774         int i,j,k=0;
775         for(i=0;i<n;i++){
776             for(j=0;j<n;j++){
777                 if(i!=j&&!mark[j]){
778                     if(c[i]==c[j]||inner(c[i],c[j])) break;
779                 }
780             }
781             if(j<n) mark[i]=1;
782         }
783         for(i=0;i<n;i++){
784             if(!mark[i]) c[k++]=c[i];
785         }
786         n=k;
787     }
788 
789     void init_add(){///圆的面积交去掉内含的圆
790         int i,j,k;
791         bool mark[1010]={0};
792         for(i=0;i<n;i++){
793             for(int j=0;j<n;j++){
794                 if(i!=j&&!mark[j]){
795                     if((c[i]==c[j])||inner(c[j],c[i])) break;
796                 }
797             }
798             if(j<n) mark[i]=1;
799         }
800         for(i=0;i<n;i++){
801             if(!mark[i]){
802                 c[k++]=c[i];
803             }
804         }
805         n=k;
806     }
807 
808     double areaarc(double th,double r){///半径为r的圆,弧度为th,对应的弓形的面积
809         return 0.5*r*r*(th-sin(th));
810     }
811 
812 
813     void getarea(){
814         memset(ans,0,sizeof(ans));
815         vector<pair<double,int> >v;
816         for(int i=0;i<n;i++){
817             v.clear();
818             v.push_back(make_pair(-PI,1));
819             v.push_back(make_pair(PI,-1));
820             for(int j=0;j<n;j++){
821                 if(i!=j){
822                     Point q=(c[j].p-c[i].p);
823                     double ab=q.len(),ac=c[i].r,bc=c[j].r;
824                     if(sgn(ab+ac-bc)<=0){
825                         v.push_back(make_pair(-PI,1));
826                         v.push_back(make_pair(PI,-1));
827                         continue;
828                     }
829                     if(sgn(ab+bc-ac)<=0)continue;
830                     if(sgn(ab-ac-bc)>0) continue;
831                     double th=atan2(q.y,q.x),fai=acos((ac*ac+ab*ab-bc*bc)/(2.0*ac*ab));
832                     double a0=th-fai;
833                     if(sgn(a0+PI)<0) a0+=2*PI;
834                     double a1=th+fai;
835                     if(sgn(a1-PI)>0) a1-=2*PI;
836                     if(sgn(a0-a1)>0){
837                         v.push_back(make_pair(a0,1));
838                         v.push_back(make_pair(PI,-1));
839                         v.push_back(make_pair(-PI,1));
840                         v.push_back(make_pair(a1,-1));
841                     }
842                     else{
843                         v.push_back(make_pair(a0,1));
844                         v.push_back(make_pair(a1,-1));
845                     }
846                 }
847                 sort(v.begin(),v.end());
848                 int cur=0;
849                 for(int j=0;j<v.size();j++){
850                     if(cur&&sgn(v[j].first-pre[cur])){
851                         ans[cur]+=areaarc(v[j].first-pre[cur],c[i].r);
852                         ans[cur]+=0.5*(Point(c[i].p.x+c[i].r*cos(pre[cur]),c[i].p.y+c[i].r*sin(pre[cur]))^Point(c[i].p.x+c[i].r*cos(v[j].first),c[i].p.y+c[i].r*sin(v[j].first)));
853                     }
854                     cur+=v[j].second;
855                     pre[cur]=v[j].first;
856                 }
857             }
858         }
859         for(int i=1;i<n;i++){
860             ans[i]-=ans[i+1];
861         }
862     }
863 };
864 
865 
866 bool Check(Line a,Line b){
867     if(sgn((a.s-a.e)^(b.s-a.e))*sgn((a.s-a.e)^(b.e-a.e))>0) return false;
868     if(sgn((b.s-b.e)^(a.s-b.e))*sgn((b.s-b.e)^(a.e-b.e))>0) return false;
869     if(sgn(max(a.s.x,a.e.x)-min(b.s.x,b.e.x))>=0&&sgn(max(b.s.x,b.e.x)-min(a.s.x,a.e.x))>=0
870      &&sgn(max(a.s.y,a.e.y)-min(b.s.y,b.e.y))>=0&&sgn(max(b.s.y,b.e.y)-min(a.s.y,a.e.y))>=0)
871         return true;
872     else return false;
873 }
874 
875 Line L[2005];
876 
877 int main(){
878     int t;
879     scanf("%d",&t);
880     Point p;
881     for(int Case=1;Case<=t;Case++){
882         double r;
883         int n;
884         scanf("%lf %d",&r,&n);
885         polygon poly;
886         halfplane hp;
887         halfplanes hps;
888         hps.n=0;
889         hp.s.x=r,hp.s.y=-r,hp.e.x=r,hp.e.y=r,hps.push(hp);
890         hp.s.x=r,hp.s.y=r,hp.e.x=-r,hp.e.y=r,hps.push(hp);
891         hp.s.x=-r,hp.s.y=r,hp.e.x=-r,hp.e.y=-r,hps.push(hp);
892         hp.s.x=-r,hp.s.y=-r,hp.e.x=r,hp.e.y=-r,hps.push(hp);
893         for(int i=1;i<=n;i++){
894             L[i].input();
895         }
896         p.input();
897         for(int i=1;i<=n;i++){
898             if(cross(L[i].s,p,L[i].e)>=0){
899                 swap(L[i].s,L[i].e);
900             }
901             hp.s=L[i].s,hp.e=L[i].e;
902             hps.push(hp);
903         }
904         if(hps.halfplaneinsert()){
905             hps.getconvex(poly);
906         }
907         circle c(0,0,r);
908         double ans1=c.area();
909         double ans2=poly.areacircle(c);
910         printf("Case %d: %.5f%%\n",Case,ans2*100/ans1);
911     }
912     return 0;
913 }
914 /*
915 
916 5 1
917 -5 0 5 3
918 0 0
919 
920 5 2
921 -5 0 5 3
922 -5 0 5 -3
923 0 0
924 
925 5 2
926 -5 0 5 3
927 -5 0 5 -3
928 0 4.9
929 
930 5 2
931 -5 0 5 3
932 -5 0 5 -3
933 0 -4.9
934 
935 1.00 2
936 -1.00 0.00 1.00 0.00
937 0.00 -1.00 0.00 1.00
938 0.50 0.50
939 
940 1.00 1
941 -1.00 0.00 1.00 0.00
942 0.50 0.50
943 
944 */
View Code

 

posted on 2019-04-27 22:53  Fighting_sh  阅读(299)  评论(0编辑  收藏  举报

导航