题目解法:实际上就是把所给的点构造出一个凸包,求出凸包的周长和以所给的最近距离为半径长度的圆的周长。构造凸包用的是Gram Scan(应该没拼错吧?我英语很烂的,原谅小弟)。
以下是代码:
-
#include "cstdio" #include "cmath" #include "algorithm" using namespace std; const int N=1005; const double eps=1e-8; const double Pi=3.1415926535;
-
struct point { int x,y; }points[N],stack[N]; int top; 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; }
-
bool cmp(point a,point b) { if(a.x!=b.x) return a.y<b.y; else return a.x<b.x; }
-
void cover_hull(int n) { int i,k,d; int miny=points[0].y,index=0; sort(points,points+n,cmp); 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() { int i,n,dist; double sum; scanf("%d%d",&n,&dist); for(i=0;i<n;i++) scanf("%d%d",&points[i].x,&points[i].y); cover_hull(n); sum=0; for(i=1;i<=top;i++) sum+=dis(stack[i-1],stack[i]); sum+=dis(stack[0],stack[top]); printf("%d/n",(int)(sum+2*Pi*dist+0.5)); return 0; }