[poj] 3348 Cows || 求凸包面积

原题

给出n个点,求得到凸包的面积


多边形面积显然很好求,就是邻边叉积之和/2。
问题在于怎么求凸包上有哪些点。凸包显然每个点都要在前两个点连线的左边(也就是逆时针位置),所以:
1、先确定一个最近的点当原点(最近:x最小的情况下y最小)
2、以该点为原点将其余点按极角排序(极角排序:约等同于将其他点按逆时针排列//因为极角啥的解释起来好麻烦的)
3、按排好的序来往凸包里添加(每次判断是不是满足粗体条件//且保证当前栈里有>=2个元素)
4、我们得到了凸包

//所以说凸包还是挺简单的啊~

#include<cstdio>
#include<algorithm>
#define N 50010
using namespace std;
int n,m,per[N];
struct point
{
    int x,y;
    point() {}
    point(int _x,int _y) : x(_x),y(_y) {}
    point operator - (const point &b) const
	{
	    return point(b.x-x,b.y-y);
	}
    double operator * (const point &b) const
	{
	    return x*b.y-b.x*y;
	}
    bool operator < (const point &b) const
	{
	    if (x==b.x) return y<b.y;
	    return x<b.x;
	}
    int norm()
	{
	    return x*x+y*y;
	}
}p[N],q[N];

bool cmp(int i,int j)
{
    int d=(p[i]-p[1])*(p[j]-p[1]);
    if (d!=0) return d>0;
    return (p[i]-p[1]).norm()<(p[j]-p[1]).norm();
}

void Graham()
{
    int id=1;
    for (int i=2;i<=n;i++)
	if (p[i]<p[id]) id=i;
    if (id!=1) swap(p[id],p[1]);
    for (int i=1;i<=n;i++) per[i]=i;
    sort(per+2,per+n+1,cmp);
    q[++m]=p[1];
    for (int i=2;i<=n;i++)
    {
	int j=per[i];
	while (m>=2 && (p[j]-q[m-1])*(q[m]-q[m-1])>=0) m--;
	q[++m]=p[j];
    }
}

int nxt(int x) { return x==m?1:x+1; }

int Area(point x,point y,point z)
{
    return (y-x)*(z-x);
}

int solve()
{
    if (m==2) return (q[2]-q[1]).norm();
    int ret=0;
    q[m+1]=q[1];
    for (int i=1,j=3;i<=m;i++)
    {
	while (nxt(j)!=i && Area(q[i],q[i+1],q[j])<=Area(q[i],q[i+1],q[j+1])) j=nxt(j);
	ret=max(ret,(q[j]-q[i]).norm());
	ret=max(ret,(q[j]-q[i+1]).norm());
    }
    return ret;
}

int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
	scanf("%d%d",&p[i].x,&p[i].y);
    Graham();
    printf("%d",solve());
    return 0;
}
原文地址:https://www.cnblogs.com/mrha/p/8111728.html