凸包-笔记

思路

1. 先找到左下角点,根据该点给其他点按极角排序

bool cmp(Pdb x,Pdb y) //按极角排序 
{
	DB b=atan2(x.se-a[1].se,x.fi-a[1].fi);
	DB c=atan2(y.se-a[1].se,y.fi-a[1].fi);
	if(b!=c) return b<c;
	if(x.fi!=y.fi) return x.fi<y.fi;
	return x.se<y.se;
}

2. 将前两个先加入栈中,对后面每个,根据叉积判断当前栈顶两个点和正在处理的点是否构成凸包。不断弹出栈顶,最后得到栈中凸包点集

代码

P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包

#include<bits/stdc++.h>
#define DB double
#define Pdb pair<double,double>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
using namespace std;
const int N=1e5+9;
int n;
DB ans;
Pdb a[N],s[N];
bool cmp(Pdb x,Pdb y) //按极角排序 
{
	DB b=atan2(x.se-a[1].se,x.fi-a[1].fi);
	DB c=atan2(y.se-a[1].se,y.fi-a[1].fi);
	if(b!=c) return b<c;
	if(x.fi!=y.fi) return x.fi<y.fi;
	return x.se<y.se;
}
bool CJ(Pdb x,Pdb y,Pdb z) //叉积 
{
	return (y.fi-x.fi)*(z.se-x.se)-(y.se-x.se)*(z.fi-x.fi)<0;
}
DB Dis(Pdb x,Pdb y)
{
	return sqrt((x.fi-y.fi)*(x.fi-y.fi)+(x.se-y.se)*(x.se-y.se));
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++)
	{
		DB x,y;
		cin>>x>>y;
		a[i]=mp(x,y);
	}
	for(int i=2;i<=n;i++) //找到左下角点 
		if(a[i].fi<a[1].fi||(a[i].fi==a[1].fi&&a[i].se<a[1].se))
			swap(a[1],a[i]);
	sort(a+1+1,a+1+n,cmp);
	int k=0,top=0;
	s[++top]=a[++k]; s[++top]=a[++k]; k++;
	while(k<=n)
	{
		if(CJ(s[top-1],s[top],a[k])) top--;
		else s[++top]=a[k++];
	}
	s[++top]=a[1];
	for(int i=2;i<=top;i++)
		ans+=Dis(s[i-1],s[i]);
	printf("%.2lf\n",ans);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值