题链:
http://poj.org/problem?id=1113
题解:
计算几何,凸包
题意:修一圈围墙把给出的点包围起来,且被包围的点距离围墙的距离不能小于L,求围墙最短为多少。
答案其实就是等于N个点的凸包的周长+半径为L的圆的周长。
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define MAXN 1050 using namespace std; const double eps=1e-8,Pi=acos(-1.0); int sign(double x){ if(fabs(x)<=eps) return 0; return x<0?-1:1; } struct Point{ double x,y; Point(double _x=0,double _y=0):x(_x),y(_y){} void Read(){scanf("%lf%lf",&x,&y);} }; typedef Point Vector; bool operator < (const Point A,const Point B){return sign(A.x-B.x)<0||(sign(A.x-B.x)==0&&sign(A.y-B.y)<0);} bool operator == (const Point A,const Point B){return sign(A.x-B.x)==0&&sign(A.y-B.y)==0;} Vector operator - (Point A,Point B){return Vector(A.x-B.x,A.y-B.y);} double operator ^ (Vector A,Vector B){return A.x*B.y-A.y*B.x;} double operator * (Vector A,Vector B){return A.x*B.x+A.y*B.y;} Point D[MAXN],H[MAXN]; int N,L; int Andrew(int dnt){ int hnt=0,k=0; sort(D+1,D+dnt+1); dnt=unique(D+1,D+dnt+1)-D-1; for(int i=1;i<=dnt;i++){ while(hnt>1&&(sign((H[hnt]-H[hnt-1])^(D[i]-H[hnt-1])))<=0) hnt--; H[++hnt]=D[i]; } k=hnt; for(int i=dnt-1;i>=1;i--){ while(hnt>k&&(sign((H[hnt]-H[hnt-1])^(D[i]-H[hnt-1])))<=0) hnt--; H[++hnt]=D[i]; } return hnt; } double GL(Vector A){//Get_Length return sqrt(A*A); } double GPC(int hnt){//Get_Polygon_Circumference double C=0; for(int i=1;i<hnt;i++) C+=GL(H[i]-H[i+1]); return C; } int main(){ while(~scanf("%d%d",&N,&L)){ for(int i=1;i<=N;i++) D[i].Read(); N=Andrew(N); printf("%.0f\n",GPC(N)+Pi*2*L); } return 0; }