题目大意:
给你N个点的坐标和一个距离限制L,让你求出1.包含所有点,2.且不能小于L;的最小周长。
思路分析:
其实就是凸包周长+圆的周长。。。。(直接套模版)。。。1A.。。。
感想:
做几何题模版很重要。。。。(平时多收集)。。。不过最重要的是自己理解。。。。
CODE:
/*计算几何:凸包周长+圆的周长*/
/*AC代码:32ms*/
#include <iostream>
#include <algorithm>
#include <cmath>
#define PI 3.14159265
#define MAXN 1005
using namespace std;
/*==================================================*\
| Graham 求凸包 O(N * logN)
| CALL: nr = graham(pnt, int n, res); res[]为凸包点集;
\*==================================================*/
struct point {double x,y;};
struct point pnt[MAXN],res[MAXN];
bool mult(point sp,point ep,point op)
{
return (sp.x-op.x)*(ep.y-op.y)>=(ep.x-op.x)*(sp.y-op.y);
}
bool operator<(const point &l,const point &r)
{
return l.y<r.y||(l.y==r.y&&l.x<r.x);
}
int graham(point pnt[],int n,point res[])//注意都是从0开始存
{
int i,len,k=0,top=1;
sort(pnt,pnt+n);
if (n == 0) return 0; res[0]=pnt[0];
if (n == 1) return 1; res[1]=pnt[1];
if (n == 2) return 2; res[2]=pnt[2];
for(i=2;i<n;i++)
{
while(top&&mult(pnt[i],res[top],res[top-1]))
top--;
res[++top]=pnt[i];
}
len=top;res[++top]=pnt[n-2];
for(i=n-3;i>=0;i--)
{
while(top!=len&&mult(pnt[i],res[top],res[top-1]))
top--;
res[++top]=pnt[i];
}
return top; // 返回凸包中点的个数
}
//----------------------------------------------------------//
double get_dis(point p1,point p2)
{return sqrt((double)((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)));}
int main()
{
int i,j,N,L;
while(scanf("%d%d",&N,&L)!=EOF)
{
for(i=0;i<N;i++)
scanf("%lf%lf",&pnt[i].x,&pnt[i].y);
int m=graham(pnt,N,res);
double ans=0;
for(i=0;i<m-1;i++)
ans+=get_dis(res[i],res[i+1]);
ans+=get_dis(res[m-1],res[0]);
ans+=2*PI*L;
int temp=(int)(ans*1000)%1000;
if(temp>=500)
printf("%d\n",(int)ans+1);
else
printf("%d\n",(int)ans);
}
return 0;
}