本样例中的2张信用卡的轮廓在上图中用实线标出,如果视1.5707963268为
Pi/2(pi为圆周率),则其凸包的周长为16+4*sqrt(2)
凸包
将图形去掉外面一层,留下中间的矩形,求出凸包,最后加上一个圆的周长。
#include<iostream> #include<cstdlib> #include<cmath> #include<cstring> #include<cstdio> #include<algorithm> #define F(i,j,n) for(int i=j;i<=n;i++) #define D(i,j,n) for(int i=j;i>=n;i--) #define ll long long #define maxn 400005 #define eps 1e-8 using namespace std; int n,cnt,top; double a,b,r,x,y,angle,ans; const double pi=acos(-1); struct P { double x,y; P(double xx=0,double yy=0){x=xx;y=yy;} friend P operator -(P a,P b){return P(a.x-b.x,a.y-b.y);} friend double operator *(P a,P b){return a.x*b.y-a.y*b.x;} friend bool operator <(P a,P b){return fabs(a.y-b.y)<eps?a.x<b.x:a.y<b.y;} }p[maxn],s[maxn]; inline P move(P a,double len,double angle) { return P(a.x+len*cos(angle),a.y+len*sin(angle)); } inline double dis(P a,P b) { return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } inline bool cmp(P a,P b) { double tmp=(a-p[1])*(b-p[1]); return fabs(tmp)<=eps?dis(p[1],a)<dis(p[1],b):tmp>0; } inline void solve() { F(i,2,cnt) if (p[i]<p[1]) swap(p[1],p[i]); sort(p+2,p+cnt+1,cmp); F(i,1,cnt) { while (top>1&&(s[top]-s[top-1])*(p[i]-s[top-1])<eps) top--; s[++top]=p[i]; } } int main() { scanf("%d",&n); scanf("%lf%lf%lf",&a,&b,&r); a-=2*r;b-=2*r;ans=2*pi*r; F(i,1,n) { scanf("%lf%lf%lf",&x,&y,&angle); F(j,1,4) { P tmp=move(P(x,y),b/2,angle+pi/2*(j-1)); p[++cnt]=move(tmp,a/2,angle+pi/2*j); swap(a,b); } } solve(); s[top+1]=s[1]; F(i,1,top) ans+=sqrt(dis(s[i],s[i+1])); printf("%.2lf\n",ans); return 0; }