凸包问题,但是可能有人对为什么最后的答案是凸包周长加一个圆的周长有疑问,参考图片,角a1与a2互补,因为另外两个角均为90度,n边形的内角和为(n-2)*180,这样的话,由于a2=180-a1,对于所有的a2的和为(n-2)*180,也可以写成n*180-a1总(因为会有n个类似a2的角,所以是n*180),a1总就是所有的a1的和,这样的话正好就是一个完整的圆,适用于所有的情况,网上很多解释冗长,不是非常好理解
代码如下:
#include<stdio.h>
#include<algorithm>
#include<math.h>
#define pi 3.1415926
using namespace std;
int n;
struct point
{
double x,y;
}p1[1000],p2[1000];
double xmult(point a,point b,point c)
{
return (a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y);
}
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 cmp(point a,point b)
{
double ans;
ans=xmult(a,b,p1[0]);
if(ans>0)
{
return 1;
}
else if(ans==0&&dis(a,p1[0])<dis(b,p1[0]))//共线情况,只选取断端点
{
return 1;
}
else
{
return 0;
}
}
int stapoint()
{
int i,k=0;
for(i=0;i<n;i++)
{
if(p1[i].y<=p1[k].y)
{
if(p1[i].y<p1[k].y)
{
k=i;
}
else
{
if(p1[i].x<p1[k].x)
{
k=i;
}
}
}
}
return k;
}
int Graham()
{
int i,sta,top;
point p3;
top=2;
if(n<=3)
{
for(i=0;i<3;i++)
{
p2[i]=p1[i];
}
return n;
}
sta=stapoint();
p3=p1[0];
p1[0]=p1[sta];
p1[sta]=p3;
sort(p1+1,p1+n,cmp);
p2[0]=p1[0];
p2[1]=p1[1];
p2[2]=p1[2];
for(i=3;i<n;i++)
{
while(xmult(p1[i],p2[top],p2[top-1])>=0)
{
top--;
}
p2[++top]=p1[i];
}
return ++top;
}
int main()
{
int i,l,num;
double len=0;
scanf("%d %d",&n,&l);
for(i=0;i<n;i++)
{
scanf("%lf %lf",&p1[i].x,&p1[i].y);
}
num=Graham();
for(i=0;i<num-1;i++)
{
len+=dis(p2[i],p2[i+1]);
}
len+=dis(p2[0],p2[num-1]);
len+=2*pi*l;
if(len-(int)len>=0.5)
{
printf("%d\n",(int)len+1);
}
else
{
printf("%d\n",(int)len);
}
return 0;
}