将每张卡四个角的圆心跑graham出正常凸包,再加上一个圆就好了。
要注意先输入的是x,找点时三角函数瞎换就过了。。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #define N 40050 #define PI 3.1415926535898 #define exp 1e-8 using namespace std; int top,tot,n; double ans; struct point{ double x,y; }p[4*N],s[4*N]; inline double sqr(double x){return x*x;} inline double dis(point a,point b){ return sqrt(sqr(a.x-b.x)+sqr(a.y-b.y)); } inline double operator *(point a,point b){ return a.x*b.y-b.x*a.y; } inline point operator - (point a,point b){ return (point){a.x-b.x,a.y-b.y}; } inline bool operator < (point a,point b){ return (fabs(a.x-b.x)<exp)?(a.y<b.y):(a.x<b.x); } bool cmp(point a,point b){ if(fabs((a-p[1])*(b-p[1]))<exp) return dis(p[1],a)<dis(p[1],b); return (a-p[1])*(b-p[1])>0; } inline point change(point a,double d,double th){ return (point){a.x+d*cos(th),a.y+d*sin(th)}; } void graham(){ top=0; for(int i=1;i<=tot;i++) if(p[i]<p[1]) swap(p[i],p[1]); sort(p+2,p+tot+1,cmp); for(int i=1;i<=tot;i++){ while(top>1&&(p[i]-s[top-1])*(s[top]-s[top-1])>exp) top--; s[++top]=p[i]; } } int main(){ scanf("%d",&n); double a,b,r,xx,yy,th; scanf("%lf%lf%lf",&a,&b,&r); a-=2*r; b-=2*r; for(int i=1;i<=n;i++){ scanf("%lf%lf%lf",&xx,&yy,&th); for(int j=0;j<4;j++){ point pp=change((point){xx,yy},b/2,th+(j)*(PI/2.0)); p[++tot]=change(pp,a/2,th+(j+1)*(PI/2.0)); swap(a,b); } } graham(); s[top+1]=s[1]; for(int i=1;i<=top;i++) ans+=dis(s[i],s[i+1]); ans+=2*PI*r; printf("%0.2lf ",ans); }