Beauty Contest(旋轉卡殼模版題)

Beauty Contest

http://poj.org/problem?id=2187ios

Time Limit: 3000MS   Memory Limit: 65536K
Total Submissions: 44329   Accepted: 13668

Descriptionide

Bessie, Farmer John's prize cow, has just won first place in a bovine beauty contest, earning the title 'Miss Cow World'. As a result, Bessie will make a tour of N (2 <= N <= 50,000) farms around the world in order to spread goodwill between farmers and their cows. For simplicity, the world will be represented as a two-dimensional plane, where each farm is located at a pair of integer coordinates (x,y), each having a value in the range -10,000 ... 10,000. No two farms share the same pair of coordinates. 

Even though Bessie travels directly in a straight line between pairs of farms, the distance between some farms can be quite large, so she wants to bring a suitcase full of hay with her so she has enough food to eat on each leg of her journey. Since Bessie refills her suitcase at every farm she visits, she wants to determine the maximum possible distance she might need to travel so she knows the size of suitcase she must bring.Help Bessie by computing the maximum distance among all pairs of farms. 

Input測試

* Line 1: A single integer, N 

* Lines 2..N+1: Two space-separated integers x and y specifying coordinate of each farm 

Outputui

* Line 1: A single integer that is the squared distance between the pair of farms that are farthest apart from each other. 

Sample Inputthis

4
0 0
0 1
1 1
1 0

Sample Outputspa

2

Hintcode

Farm 1 (0, 0) and farm 3 (1, 1) have the longest distance (square root of 2) 

 

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