分析:给你n个点的坐标和半径l,求形成的凸包的周长和一个圆的周长和,结果4舍5入。求凸包就用Graham扫描法就好了,以下附两个代码,意思都差不多,要注意的是,double类型的变量存在误差,所以判断是否相等时应该是:a-b<0.000000001 而不是 a==b,做的时候没注意,一直WA。
版本一:
# include <stdio.h> # include <math.h> # include <algorithm> # define PI acos(-1.0) # define EPS 1e-8 using namespace std; struct point { double x,y,cos; }v[1005]; double Cross(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double Dis(point a,point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } int cmp(point a,point b) { if(fabs(a.cos-b.cos)>EPS) return a.cos>b.cos; if(fabs(a.y-b.y)>EPS) return a.y<b.y; return a.x<b.x; } int main() { int i,n,l,min,stack[1005],top; double ans,x,y; scanf("%d%d",&n,&l); for(i=0,min=0;i<n;i++) { scanf("%lf%lf",&v[i].x,&v[i].y); if(v[i].y<v[min].y||(v[i].y==v[min].y&&v[i].x<v[min].x)) min=i; } x=v[0].x;y=v[0].y; v[0].x=v[min].x;v[0].y=v[min].y; v[min].x=x;v[min].y=y; for(i=1;i<n;i++) v[i].cos=(v[i].x-v[0].x)/Dis(v[i],v[0]); sort(v+1,v+n,cmp); top=-1;stack[++top]=0;stack[++top]=1; for(i=2;i<n;) { if(Cross(v[stack[top-1]],v[stack[top]],v[i])>=0) stack[++top]=i++; else top--; } for(i=0,ans=0;i<=top;i++) ans+=Dis(v[stack[i]],v[stack[(i+1)%(top+1)]]); ans+=2.0*PI*l; printf("%d\n",(int)(ans+0.5)); return 0; }
版本二:
# include <stdio.h> # include <math.h> # include <algorithm> # define PI acos(-1.0) using namespace std; struct point { int x,y; }v[1005]; int Cross(point a,point b,point c) { return (b.x-a.x)*(c.y-a.y)-(c.x-a.x)*(b.y-a.y); } double Dis(point a,point b) { return sqrt((double)((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y))); } int cmp(point a,point b) { int t=Cross(v[0],a,b); if(t!=0) return t>0?1:0; return Dis(v[0],a)<Dis(v[0],b); } void Graham(int n,int l) { int i,min,top; point t,stack[1005]; double ans; for(i=0,min=0;i<n;i++) if(v[i].y<v[min].y||(v[i].y==v[min].y&&v[i].x<v[min].x)) min=i; t=v[0]; v[0]=v[min]; v[min]=t; sort(v+1,v+n,cmp); top=-1; stack[++top]=v[0]; stack[++top]=v[1]; for(i=2;i<n;i++) { while(top>0&&Cross(stack[top-1],stack[top],v[i])<=0) top--; stack[++top]=v[i]; } for(i=0,ans=0;i<=top;i++) ans+=Dis(stack[i],stack[(i+1)%(top+1)]); printf("%d\n",(int)(ans+2*PI*l+0.5)); } int main() { int i,n,l; scanf("%d%d",&n,&l); for(i=0;i<n;i++) scanf("%d%d",&v[i].x,&v[i].y); Graham(n,l); return 0; }