求凸包的周长和以所给半径长度的圆的周长,基本上是一个模版题。
以下是代码:
- #include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
const int M=110;
const double eps=1e-6;
const double Pi=acos(-1.0); - struct point
{
double x,y;
}points[M],stack[10*M];
int top,n;
double r; - double dis(point a,point b)
{
return sqrt((a.x-b.x)*(a.x-b.x)*1.0+(a.y-b.y)*(a.y-b.y));
} - double crossmulti(point p0,point p1,point p2)
{
return (p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
} - bool cmp1(point p,point q)
{
double k=crossmulti(points[0],p,q);
if(k<-eps)
return 0;
else if(fabs(k)<eps && (dis(p,points[0])-dis(q,points[0]))>eps)
return 0;
else return 1;
} - void cover_hull(int n)
{
int i,k,d;
int index=0;
double miny=points[0].y;
for(i=1;i<n;i++)
{
if(points[i].y<miny)
{
miny=points[i].y;
index=i;
}
else if(points[i].y==miny && points[i].x<points[index].x)
{
index=i;
}
}
point temp;
temp=points[index];
points[index]=points[0];
points[0]=temp;
sort(points+1,points+n,cmp1);
stack[0]=points[n-1];
stack[1]=points[0];
top=1;
k=1;
while(k<=n-1)
{
double d=crossmulti(stack[top],stack[top-1],points[k]);
if(d<=0)
{
top++;
stack[top]=points[k];
k++;
}
else top--;
}
} - int main()
{
while(scanf("%d%lf",&n,&r)==2)
{
int i,j;
for(i=0;i<n;i++)
scanf("%lf%lf",&points[i].x,&points[i].y);
if(n==1)
{
printf("%.2lf/n",2.0*Pi*r);
continue;
}
cover_hull(n);
double ans=0;
for(i=0;i<top-1;i++)
{
ans+=sqrt((stack[i].x-stack[i+1].x)*(stack[i].x-stack[i+1].x)+(stack[i].y-stack[i+1].y)*(stack[i].y-stack[i+1].y));
}
ans+=sqrt((stack[0].x-stack[top-1].x)*(stack[0].x-stack[top-1].x)+(stack[0].y-stack[top-1].y)*(stack[0].y-stack[top-1].y));
printf("%.2lf/n",ans+2.0*Pi*r);
}
return 0;
}