凸包---HDU 2202

题意:给N个点,求着N个点中选择三个联的最大的三角形面积!

注意精度:不然OJ上面会超时的

 

#include<iostream>

#include<cmath>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

const double eps = 1e-8;

using namespace std;

struct point

{

    int x,y;

} p[50005],res[50005];

int cross(point p0, point p1, point p2)//计算叉积

{

    return(p1.x- p0.x) * (p2.y- p0.y) - (p1.y- p0.y) * (p2.x- p0.x);

}//顺时针扫描,判断大于0(方向改变)的加入凸包,然后回溯

double  dist(point a,point b)//两点距离

{

    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

}

bool cmp(point  a, point  b)//按照y小到大排序,y相等按照x小到大排序

{

    return(a.y< b.y|| (a.y== b.y&& a.x< b.x));

}

int Graham(int n)//求凸包,返回凸包上顶点的个数

{

    int len, top=1;

    sort(p, p+ n, cmp);

    res[0] = p[0];

    res[1] = p[1];

    for(int i=2; i< n; i++)

    {

        while(top&& cross(res[top], res[top-1], p[i])<=eps)top--;

        res[++ top] = p[i];

    }

    len= top;

    res[++ top] = p[n-2];

    for(int i= n-3; i>=0; i--)

    {

        while(top!= len&& cross(res[top], res[top-1], p[i])<=eps)top--;//注意精度问题,不然会超时的

        res[++ top] = p[i];

    }

    return top;

}

int main()

{

    int n,top;

    while(scanf("%d",&n)!=EOF)

    {

        double MAX=-1;

        for(int i=0; i<n; i++)

            scanf("%d%d", &p[i].x ,&p[i].y);

        top=Graham(n);

        for(int i=0; i<top-2; i++)

            for(int j=i+1; j<top-1; j++)

                for(int k=j+1; k<top; k++)

                {

                      double ss=fabs(cross(res[i],res[j],res[k]));

                      if(ss>MAX) MAX=ss;//暴力利用叉积计算三角形的面积

                }

        printf("%.2f\n",MAX/2.0);

    }

    return 0;

}

另一个版本的凸包

#include<iostream>

#include<cmath>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

const double eps = 1e-8;

using namespace std;

struct point

{

    int x,y;

} p[50005],res[50005];

int cross(point p0, point p1, point p2)//计算叉积

{

    return(p1.x- p0.x) * (p2.y- p0.y) - (p1.y- p0.y) * (p2.x- p0.x);

}//顺时针扫描,判断大于0(方向改变)的加入凸包,然后回溯

double  dist(point a,point b)//两点距离

{

    return sqrt((double)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));

}

bool cmp(point  a, point  b)//极角排序,先用arctan()判断角大小,角度由小到大,然后用距离小到大排序

{

     double t1 = atan2(a.y - p[0].y, a.x - p[0].x);

     double t2 = atan2(b.y - p[0].y, b.x - p[0].x);

     return t1>t2||(t1==t2&&dist(p[0],a)<dist(p[0],b));

}

int Graham(int n)//求凸包,返回凸包上顶点的个数

{

    int len, top,tmp=0;

    for(int i=1;i<n;i++)

        if(p[tmp].y>p[i].y||(p[tmp].y==p[i].y&&p[tmp].x>p[i].x))

            tmp=i;

    swap(p[0],p[tmp]);//找出最左下角的点

    sort(p+1, p+ n,cmp);

    res[0] = p[0];

    res[1] = p[1];

    res[2] =p[2];

    top=2;

    for(int i=2; i<n; i++)

    {

        while(top>=2&& cross(res[top], res[top-1], p[i])<=eps)top--;

        res[++ top] = p[i];

    }//只用一次扫描

    res[++top]=p[n-1];//完了要把最后一个点加上去

    return top;

}

int main()

{

    int n,top;

    while(scanf("%d",&n)!=EOF)

    {

        double MAX=-1;

        for(int i=0; i<n; i++)

            scanf("%d%d", &p[i].x ,&p[i].y);

        top=Graham(n);

        for(int i=0; i<top-2; i++)

            for(int j=i+1; j<top-1; j++)

                for(int k=j+1; k<top; k++)

                {

                      double ss=fabs(cross(res[i],res[j],res[k]));

                      if(ss>MAX) MAX=ss;//暴力利用叉积计算三角形的面积

                }

        printf("%.2f\n",MAX/2.0);

    }

    return 0;

}




 

 

你可能感兴趣的:(HDU)