凸包模板
来源:互联网 发布:淘宝网购物14男童装 编辑:程序博客网 时间:2024/05/16 05:50
//求凸包问题#include <iostream>#include <stdio.h>#include <cmath>#include <algorithm>using namespace std;const double PI = 3.14159265358979;struct point{ double x,y; double thera;} a[1005],chs[1005];bool cmp1(point a,point b) //寻找左下角的点{ if( a.y == b.y ) return a.x < b.x; return a.y < b.y;}bool cmp2(point a,point b){ if( a.thera == b.thera ) //极角相同按x位置升序 return a.x < b.x; else return a.thera < b.thera;}double get_thera(point a0,point a1) //求两点直线与x轴的夹角{ return atan2((a1.y-a0.y),(a1.x-a0.x));}double dist_2point(point a1,point a2) //两点距离{ return sqrt((a1.x-a2.x)*(a1.x-a2.x)+(a1.y-a2.y)*(a1.y-a2.y));}bool line_3point(point a1,point a2,point a3){ double P,Q,M; //又是那个原理:求点在直线的左边还是右边。(叉乘!) P=(a2.x - a1.x) * (a3.y - a1.y); Q=(a3.x - a1.x) * (a2.y - a1.y); M=P-Q; if(M>0) return false; //负数 说明在向量的右边,是顺时针旋转的。 if(M<0) return true; //正数 说明在向量的左边,是逆时针旋转的。 if(M==0) return true; //零 说明线段的直线上,则点(x3,y3)是共线。 //return false;}int main(){ #ifndef ONLINE_JUDGE freopen("in.txt","r",stdin); #endif // ONLINE_JUDGE int i,n,top; double r,len,shan,sum; while(scanf("%d%lf",&n,&r)!=EOF) { len=0; for(i=0; i<n; i++) scanf("%lf%lf",&a[i].x,&a[i].y); ///求左下角的点(以它未基准) y最小,若相同,x要最小。 sort(a,a+n,cmp1); ///下面就是极角排序 for(i=0; i<n; i++) //求两点连线与x轴夹角 a[i].thera=get_thera(a[0],a[i]); //得到夹角的弧度 sort(a+1,a+n,cmp2); //对夹角进行由小到大的排序 ///下面就是Wall Graham_Scan算法 chs[0]=a[0]; chs[1]=a[1]; chs[2]=a[2]; top=2; for(i=3; i<n; i++) { while(top>=1 && line_3point(chs[top-1],chs[top],a[i])) { top--; } chs[++top]=a[i]; //chs[]就是凸包的点 } ///这样求出chs[]的点就是凸包的所有顶点!!!(逆时针) top++; //小心注意!因为最后chs[++top]=a[i],所以要top++! for(i=0; i<top; i++) len+=dist_2point(chs[i%top],chs[(i+1)%top]); shan=2.0*PI*r; sum=shan+len; printf("%.0lf\n",sum); } return 0;}