http://poj.org/problem?id=1113
题目大意
国王给自己的城堡建围墙,围墙要和城堡保持一定距离L
凸包,保持一定的距离只不过多了一个圆弧长度而已(PI*2*L)
因为所有拐点处的圆弧加在一起是一个圆
#include<iostream> #include<cmath> #include<string> #include<algorithm> #include<queue> #include<cstring> #include<cstdio> using namespace std; const double PI=acos(-1); const int N=1005; struct node { int x,y; }mem[N]; int used_point[N]; double dist(int i,int j)//求两点距离 { return sqrt((mem[i].x-mem[j].x)*(mem[i].x-mem[j].x) +(mem[i].y-mem[j].y)*(mem[i].y-mem[j].y)); } bool cmp(node l1,node l2)//叉积排序 如果相等 近的优先 { if((l1.x-mem[0].x)*(l2.y-mem[0].y)==(l2.x-mem[0].x)*(l1.y-mem[0].y)) return ((l1.x-mem[0].x)*(l1.x-mem[0].x)+(l1.y-mem[0].y)*(l1.y-mem[0].y))< ((mem[0].x-l2.x)*(mem[0].x-l2.x)+(mem[0].y-l2.y)*(mem[0].y-l2.y)); return (l1.x-mem[0].x)*(l2.y-mem[0].y)>(l2.x-mem[0].x)*(l1.y-mem[0].y); } bool Left_turn(int i,int j,int l)//判断是否左转 { int x1=mem[j].x-mem[i].x; int y1=mem[j].y-mem[i].y; int x2=mem[l].x-mem[j].x; int y2=mem[l].y-mem[j].y; if(x1*y2>x2*y1)//如果左转 true (这种情况为不要直线上多余的点 如果想要应用 >=) return true; return false; } int main() { int n,l; while(scanf("%d %d",&n,&l)!=EOF) { int k=0; for(int i=0;i<n;++i) { scanf("%d %d",&mem[i].x,&mem[i].y); if(mem[i].y<mem[k].y||(mem[i].y==mem[k].y&&mem[i].x<mem[k].x)) k=i; } if(k!=0) { swap(mem[0].x,mem[k].x); swap(mem[0].y,mem[k].y); } sort(mem+1,mem+n,cmp); int I=0; used_point[I++]=0; used_point[I++]=1; used_point[I++]=2; for(int i=3;i<n;) { if(I<2||Left_turn(used_point[I-2],used_point[I-1],i))//是左转则入栈加一 (I<2)的情况是对于开始就有直线又不要直线上多余点的情况, //防止越界。如果直线上多余的点也要则可不写,但会有多余的点使得效率低 used_point[I++]=i++; else//否则出栈 --I; } used_point[I]=used_point[0]; double ans=0.0; for(int i=0;i<I;++i) { ans=ans+dist(used_point[i],used_point[i+1]); } ans=ans+(PI*2*l); printf("%d\n",int(ans+0.5)); } return 0; }