1. 程式人生 > >POJ 3348 Cows | 凸包模板題

POJ 3348 Cows | 凸包模板題

nor clas body 模板 block ron pac ring 進行

題目:

給幾個點,用繩子圈出最大的面積養牛,輸出最大面積/50


題解:

Graham凸包算法的模板題

下面給出做法

1.選出x坐標最小(相同情況y最小)的點作為極點(顯然他一定在凸包上)

2.其他點進行極角排序<極角指從坐標軸的某一方向逆時針旋轉到向量的角度>,

 極角一樣按距離從近到遠(可以用叉積實現)

3.用棧維護凸包上的點,將極點和極角序最小的點依次入棧

4.按順序掃描,檢查棧頂的前兩個元素與這個點構成的線段是否拐向右(順時針側,叉積小於0)

 如果滿足就彈出棧頂元素,直到不滿足或者棧裏不足兩個元素

 反之入棧

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
#define N 10005
using namespace std;
int n,m;
struct point
{
    int x,y;
    point (){};
    point (int _x,int _y)
	{
	    x=_x,y=_y;
	}
    point operator - (const point &a)const
	{
	    return point (x-a.x,y-a.y);
	}
    int operator * (const point &a) const
	{
	    return x*a.y-y*a.x;
	}
    int norm()const
	{
	    return x*x+y*y;
	}
}p[N],q[N];
bool cmp(int u,int v)
{
    int det=(p[u]-p[1])*(p[v]-p[1]);
    if (det!=0) return det>0;
    return (p[u]-p[1]).norm() < (p[v]-p[1]).norm();
}
void Graham()
{
    int id=1;
    for (int i=2;i<=n;i++)
	if (p[i].x<p[id].x || (p[i].x==p[id].x && p[i].y<p[id].y))
	    id=i;
    if (id!=1) swap(p[1],p[id]);
    int per[N];
    for (int i=1;i<=n;i++)
	per[i]=i;
    sort(per+2,per+1+n,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 Area()
{
    int res=0;
    q[m+1]=q[1];
    for (int i=1;i<=m;i++)
	res+=q[i]*q[i+1];
    return res/2;
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
	scanf("%d%d",&p[i].x,&p[i].y);
    Graham();
    int ans=Area()/50;
    printf("%d\n",ans);
    return 0;
}

POJ 3348 Cows | 凸包模板題