把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

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

题面传送门
鸽了大半个月了回来补掉了这道题。
按照坐标轴排序的比极角序不知道好写多少啊。
首先按照\(x\)为第一关键字,\(y\)为第二关键字排序。
然后用叉积判断当前栈内的点和要入栈的点的位置关系,如果顺时针就弹掉。
然后这样可以构造出下凸壳。再来一遍构造上凸壳即可。
code:

#include<cstdio>
#include<cmath>
#include<algorithm>
#define I inline
#define N 100039
#define re register
#define ll long long
#define db double
using namespace std;
int n,m,k,x,y,z,sh=-1,tot=1;db ans;
struct yyy{db a,b;}f[N],st[N];
I bool cmp(yyy x,yyy y){return x.a==y.a?(x.b<y.b):(x.a<y.a);} 
I db dis(yyy x,yyy y){return sqrt((x.a-y.a)*(x.a-y.a)+(x.b-y.b)*(x.b-y.b));}
I ll make(yyy x,yyy y,yyy a,yyy b){return (y.a-x.a)*(b.b-a.b)-(y.b-x.b)*(b.a-a.a);}
int main(){
	freopen("1.in","r",stdin);
	register int i;
	scanf("%d",&n);
	for(i=1;i<=n;i++) scanf("%lf%lf",&f[i].a,&f[i].b);sort(f+1,f+n+1,cmp);
	for(i=1;i<=n;i++){
		while(sh>=1&&make(st[sh-1],st[sh],st[sh-1],f[i])<0) sh--;
		st[++sh]=f[i];
	}
	for(i=1;i<=sh;i++) ans+=dis(st[i],st[i-1]);sh=-1;
	for(i=n;i;i--){
		while(sh>=1&&make(st[sh-1],st[sh],st[sh-1],f[i])<0) 
		sh--;
		st[++sh]=f[i];
	}
	for(i=1;i<=sh;i++) ans+=dis(st[i],st[i-1]);printf("%.2lf\n",ans);
}
posted @ 2021-04-03 22:36  275307894a  阅读(45)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end