Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 4903 Accepted Submission(s): 1419
#include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> using namespace std; const int N = 1005; const double pi = atan(1.0)*4; const double eps = 1e-8; struct Point { double x,y; } p[N]; Point Stack[N]; ///模拟栈,不然的话取到栈的第二个元素不好处理 double mult(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 (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y); } int n,m; int cmp(Point a,Point b) ///设<p1,p2,...pm>为对其余点按以p0为中心的极角逆时针排序所得的点集(如果有多个点有相同的极角,除了距p0最远的点外全部移除) { if(mult(a,b,p[0])>0) return 1; if(mult(a,b,p[0])==0&&dis(b,p[0])-dis(a,p[0])>eps) return 1; return 0; } int Graham() { int top=2; ///栈顶在2,因为凸包的前两个点是不会变了 sort(p+1,p+n,cmp); Stack[0]=p[0]; ///压p0p1p2进栈S Stack[1]=p[1]; Stack[2]=p[2]; for(int i=3;i<n;i++){ while(top>=1&&mult(p[i],Stack[top],Stack[top-1])>=0){///有了更好的选择 top--; } Stack[++top]=p[i]; } return top; } int main() { int tcase; scanf("%d",&tcase); while(tcase--) { scanf("%d%d",&n,&m); for(int i=0; i<n; i++) { scanf("%lf%lf",&p[i].x,&p[i].y); } int k = 0; for(int i=0; i<n; i++) ///令p0为Q中Y-X坐标排序下最小的点 { if(p[k].y>p[i].y||((p[k].y==p[i].y)&&(p[k].x>p[i].x))) { k=i; } } swap(p[0],p[k]); double sum=0; int top = Graham(); for(int i=1;i<=top;i++){ sum+=sqrt(dis(Stack[i],Stack[i-1])); } ///处理最后一个点和P0 sum+=sqrt(dis(Stack[0],Stack[top])); ///加上圆 sum+=2*pi*m; printf("%.0lf\n",sum); if(tcase) printf("\n"); } return 0; }
原文:http://www.cnblogs.com/liyinggang/p/5428048.html