题意:
题目链接
题目大意:
给出n个四角为pi/4的圆弧的类矩形,求它们凸包的周长
思路:
乍看似乎没有思路,但注意到r=0时求的是一个裸的凸包
考虑当r不等于0时,我们先按之前的方法求出凸包周长
然后对于每个拐点求其角度,而后求出这段圆弧长,累加即可。。。
for(int i=1;i<=m;++i)
{
ans+=(q[i]-q[i+1]).dist();
double cs=((q[i]-q[i+1])*(q[i+2]-q[i+1]))/(q[i]-q[i+1]).dist()/(q[i+1]-q[i+2]).dist();
//点乘a*b=|a||b|cos<a,b>(a,b为向量)
double dg=pi-acos(cs);
ans+=dg*r;
}
最后提交AC后看了遍题解,发现圆弧累加后的总长度就是一个整圆的周长,直接加就可以了。
for(int i=1;i<=m;++i)
ans+=(q[i]-q[i+1]).dist();
ans+=2*pi*r;
注意事项:
pi指180度,而不是360度(这种错只有我才犯吧。。。)
code:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const double eps=1e-7;
const double pi=3.1415926535898;
int n,m,cnt,per[N<<2];
double a,b,r;
struct point{double x,y;double dist(){return sqrt(x*x+y*y);}}p[N<<2],q[N<<2];
point operator+(point x,point y){return (point){x.x+y.x,x.y+y.y};}
point operator-(point x,point y){return (point){x.x-y.x,x.y-y.y};}
double operator*(point x,point y){return x.x*y.x+x.y*y.y;}
double operator^(point x,point y){return x.x*y.y-x.y*y.x;}
inline double readin(){double x;scanf("%lf",&x);return x;}
inline double lfabs(double x){return x<-eps?-x:x;}
inline point rot(point pp,double dg)
{
return (point){pp.x*cos(dg)-pp.y*sin(dg),pp.y*cos(dg)+pp.x*sin(dg)};
}
struct cmpfunctor{
inline bool operator()(int x,int y)
{
double dit=(p[x]-p[1])^(p[y]-p[1]);
if(lfabs(dit)>eps) return dit>eps;
return (p[x]-p[1]).dist()<(p[y]-p[1]).dist();
}
};
inline void Graham()
{
for(int i=2;i<=cnt;++i)
if(p[i].x-p[1].x<-eps||(lfabs(p[i].x-p[1].x)<eps&&p[i].y-p[1].y<-eps))
swap(p[1],p[i]);
for(int i=1;i<=cnt;++i)per[i]=i;
sort(per+2,per+cnt+1,cmpfunctor());
q[++m]=p[1];
for(int i=2;i<=cnt;++i)
{
int j=per[i];
while(m>1&&((p[j]-q[m-1])^(q[m]-q[m-1]))>-eps) --m;
q[++m]=p[j];
}
q[m+1]=q[1];q[m+2]=q[2];
}
inline double C()
{
double ans=0;
for(int i=1;i<=m;++i)
ans+=(q[i]-q[i+1]).dist();
return ans+2.0*pi*r;
}
int main()
{
scanf("%d",&n);
scanf("%lf%lf%lf",&a,&b,&r);
for(int i=1;i<=n;++i)
{
point pt;scanf("%lf%lf",&pt.x,&pt.y);
point ne=(point){pt.x+b/2.0-r,pt.y+a/2.0-r};
point nw=(point){pt.x-b/2.0+r,pt.y+a/2.0-r};
double dg=readin();
p[++cnt]=rot(ne-pt,dg)+pt;p[++cnt]=rot(nw-pt,dg)+pt;
point ps=pt+pt-p[cnt];p[++cnt]=ps;
ps=pt+pt-p[cnt-2];p[++cnt]=ps;
}
Graham();
printf("%.2lf",C());
return 0;
}