UVA 218 Moth Eradication(凸包应用)
题意:
给你n个点的集合,要你求出这个点集的凸包(求凸包最小点集),并且按时针输出所有点,且输出该凸包的周长.
分析:
直接用刘汝佳训练指南P272求凸包的模板即可,不过注意要小心n=1或2的情况. 刘汝佳的模板可以直接处理n=>1的所有情况.
注意:本题的输出点从x坐标最小的值开始(x坐标相同就输出y坐标最小的)按顺时针顺序输出所有点坐标. 两个输出实例之间要有空格.
AC代码:
#include<cstdio> #include<cstring> #include<cmath> #include<algorithm> using namespace std; const double eps=1e-10; int dcmp(double x) { if(fabs(x)<eps) return 0; return x<0?-1:1; } struct Point { double x,y; Point(){} Point(double x,double y):x(x),y(y){} bool operator==(const Point& rhs)const { return dcmp(x-rhs.x)==0 && dcmp(y-rhs.y)==0; } bool operator<(const Point& rhs)const { return dcmp(x-rhs.x)<0 || (dcmp(x-rhs.x)==0 && dcmp(y-rhs.y)<0); } }; typedef Point Vector; double dist(Point a,Point b) { return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y)); } Vector operator-(Point A,Point B) { return Vector(A.x-B.x,A.y-B.y); } double Cross(Vector A,Vector B) { return A.x*B.y-A.y*B.x; } int ConvexHull(Point *p,int n,Point *ch) { sort(p,p+n); n=unique(p,p+n)-p; int m=0; for(int i=0;i<n;i++) { while(m>1 && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-1])<=0) m--; ch[m++]=p[i]; } int k=m; for(int i=n-2;i>=0;i--) { while(m>k && Cross(ch[m-1]-ch[m-2], p[i]-ch[m-1])<=0) m--; ch[m++]=p[i]; } if(n>1) m--; return m; } const int maxn=10000+5; Point p[maxn],ch[maxn]; int main() { int n,kase=0; while(scanf("%d",&n)==1 && n) { if(kase>0) printf("\n"); for(int i=0;i<n;i++) scanf("%lf%lf",&p[i].x,&p[i].y); int m=ConvexHull(p,n,ch); double ans=0; printf("Region #%d:\n",++kase); printf("(%.1lf,%.1lf)",ch[0].x,ch[0].y); for(int i=m-1;i>=0;i--) { printf("-(%.1lf,%.1lf)",ch[i].x,ch[i].y); ans += dist(ch[i],ch[(m+i-1)%m]); } printf("\n"); if(m==1) ans=0; else if(m==2) ans/=2; printf("Perimeter length = %.2lf\n",ans); } return 0; }