凸包模板

来源:互联网 发布:淘宝网购物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;}

原创粉丝点击