BZOJ 2829 凸包
思路:
把信用卡周围去掉 只剩下中间的长方形
最后的答案加上一个圆
//By SiriusRen #include <bits/stdc++.h> using namespace std; const int N=50000; const double eps=1e-10; int card,n,m,k; double a,b,r,xx,yy,theta,Ans; struct Point{ double x,y;Point(){} Point(double X,double Y){x=X,y=Y;} }point[N],tubao[N]; bool cmp1(Point a,Point b){if(abs(a.x-b.x)>eps)return a.x<b.x;return a.y<b.y;} double cross(Point a,Point b,Point c){ return (a.x-c.x)*(b.y-c.y)-(a.y-c.y)*(b.x-c.x); } double dis(Point a,Point b){ return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int main(){ scanf("%d%lf%lf%lf",&card,&a,&b,&r); Ans+=2*acos(-1)*r; a=a-2*r,b=b-2*r; for(int i=1;i<=card;i++){ scanf("%lf%lf%lf",&xx,&yy,&theta); point[++n]=Point(xx-sin(theta)*a/2-cos(theta)*b/2,yy+cos(theta)*a/2-sin(theta)*b/2); point[++n]=Point(xx-sin(theta)*a/2+cos(theta)*b/2,yy+cos(theta)*a/2+sin(theta)*b/2); point[++n]=Point(xx+sin(theta)*a/2-cos(theta)*b/2,yy-cos(theta)*a/2-sin(theta)*b/2); point[++n]=Point(xx+sin(theta)*a/2+cos(theta)*b/2,yy-cos(theta)*a/2+sin(theta)*b/2); } sort(point+1,point+1+n,cmp1); for(int i=1;i<=n;i++){ while(m>1&&cross(tubao[m],point[i],tubao[m-1])<eps)m--; tubao[++m]=point[i]; }k=m; for(int i=n-1;i;i--){ while(m>k&&cross(tubao[m],point[i],tubao[m-1])<eps)m--; tubao[++m]=point[i]; } for(int i=1;i<m;i++)Ans+=dis(tubao[i],tubao[i+1]); printf("%.2lf\n",Ans); }