求凸包 cogs896

   cogs炸了,所以暂没有题面。

    最基础的板子,因为根据点从左到右,横轴相同纵轴从下到上的顺序排了序,正向一遍求下壳(念什么?qiao:ke)再翻一遍求上壳,出入栈的原理就是根据叉乘逆时针为正,顺时针为负来判断是否外凸。想不明白可以画下图。

    剩下就是扔个板子了。

    

#define e 1e-8
 
#include <cmath>
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
int n;
struct vec
{
	double x,y;
	inline friend bool operator < (vec a,vec b)
	{
		if(a.x==b.x)return a.y<b.y;
		return a.x<b.x;
	}
	inline friend vec operator -(vec a,vec b)
	{
		return (vec){a.x-b.x,a.y-b.y};
	}
} a[10005];
int zhan[10005],head=0,vis[10005];
double ans=0;
vector<vec> hh;
double S(vec a,vec b)
{
	return a.x*b.y-b.x*a.y;
}
bool check(vec a,vec b,vec c)
{
	return S(b-a,c-a)>e;
}
double pf(double x)
{
	return x*x;
}
double jl(vec a,vec b)
{
	return sqrt(pf(a.x-b.x)+pf(a.y-b.y));
}
int yjn()
{
//	freopen("fc.in","r",stdin);
//	freopen("fc.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	  scanf("%lf%lf",&a[i].x,&a[i].y);
	sort(a+1,a+n+1);
	zhan[++head]=1;zhan[++head]=2;
	for(int i=3;i<=n;i++)
	{
	    while(head>1&&!check(a[zhan[head]],a[i],a[zhan[head-1]]))head--;
	       zhan[++head]=i;
	}
	for(int i=1;i<=head;i++)vis[zhan[i]]=1,hh.push_back(a[zhan[i]]);
	head=0;
	zhan[++head]=n;
	zhan[++head]=n-1;
	for(int i=n-2;i>=1;i--)
	{
	    while(head>1&&check(a[zhan[head]],a[zhan[head-1]],a[i]))head--;
	        zhan[++head]=i;
	}
	for(int i=1;i<=head;i++)if(!vis[zhan[i]])hh.push_back(a[zhan[i]]),vis[zhan[i]]=1;
	for(int i=0,s=hh.size();i<s;i++)
		ans+=jl(hh[i],hh[(i+1)%s]);
	printf("%.2lf",ans);
} 
int qty=yjn();
int main(){;}


原文地址:https://www.cnblogs.com/QTY2001/p/7632743.html