计算几何(凸包):SHTSC 2012 信用卡凸包

  这道题是水题,发现平移某些边,答案就是圆心的凸包+一个圆的周长。

  不要忽视精度误差!

 1 #include <algorithm>
 2 #include <iostream>
 3 #include <cstring>
 4 #include <cstdio>
 5 #include <cmath>
 6 using namespace std;
 7 const int N=100010;
 8 const double eps=1e-8;
 9 const double Pi=acos(-1.0); 
10 int sgn(double x){
11     if(x>eps)return 1;
12     if(x<-eps)return -1;
13     return 0;
14 }
15 struct Point{
16     double x,y;
17     Point(double _=0,double __=0){x=_;y=__;}
18     friend Point operator+(Point a,Point b){
19         return Point(a.x+b.x,a.y+b.y);
20     } 
21     friend Point operator-(Point a,Point b){
22         return Point(a.x-b.x,a.y-b.y);
23     }
24     friend bool operator<(Point a,Point b){
25         return sgn(a.y-b.y)?sgn(b.y-a.y)>0:sgn(b.x-a.x)>0;
26     }
27 }st[4*N],p[4*N];
28 double Cross(Point a,Point b){
29     return a.x*b.y-a.y*b.x;
30 }
31 
32 Point Rotate(Point a,double th){
33     double s=sin(th),c=cos(th);
34     return Point(a.x*c-a.y*s,a.x*s+a.y*c);
35 }
36 
37 double sqr(double x){return x*x;}
38 double Dis(Point a,Point b){
39     return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y));
40 }
41 
42 bool cmp(Point a,Point b){
43     double c=Cross(a-p[0],b-p[0]);
44     if(sgn(c)>0)return true;
45     if(sgn(c)<0)return false;
46     return sgn(Dis(p[0],b)-Dis(p[0],a))>0;
47 }
48 
49 double a,b,r;
50 double x,y,th;
51 int n,pos,top,tot;
52 int main(){
53     freopen("card.in","r",stdin);
54     freopen("card.out","w",stdout);
55     scanf("%d",&n);
56     scanf("%lf%lf%lf",&b,&a,&r);
57     a=a/2.0;a=a-r;b=b/2.0;b=b-r;
58     for(int i=1;i<=n;i++){
59         scanf("%lf%lf%lf",&x,&y,&th);
60         Point O(x,y);
61         p[i*4-4]=Rotate(Point(x+a,y+b)-O,th)+O;
62         p[i*4-3]=Rotate(Point(x+a,y-b)-O,th)+O;
63         p[i*4-2]=Rotate(Point(x-a,y+b)-O,th)+O;
64         p[i*4-1]=Rotate(Point(x-a,y-b)-O,th)+O;
65     }
66     sort(p,p+4*n);
67     for(int i=0;i<4*n;i++){
68         if(i==0)p[tot++]=p[i];
69         else if(sgn(p[i].x-p[i-1].x)||sgn(p[i].y-p[i-1].y))
70             p[tot++]=p[i];
71     }
72     sort(p+1,p+tot,cmp);p[tot]=p[0];
73     st[1]=p[0];st[2]=p[1];top=2;
74     for(int i=2;i<=tot;i++){
75         while(top>=2&&sgn(Cross(st[top]-p[i],st[top-1]-p[i]))>=0)top--;
76         st[++top]=p[i];
77     }
78     double ans=2.0*Pi*r;
79     for(int i=2;i<=top;i++)
80         ans+=Dis(st[i],st[i-1]);
81     printf("%.2f\n",ans);
82     return 0;
83 }

 

posted @ 2016-10-28 14:03  TenderRun  阅读(368)  评论(0编辑  收藏  举报