二维凸包

二维凸包模板

其实二维凸包是个很简单的东西
想象一下我们在二维平面上打了很多柱子,凸包其实就是往上面套橡皮筋,收到最紧就是了

我们把这些桩子按照x,y从小到大排序
发现什么呢?数组内第一个和最后一个点一定在凸包上
为什么呢?我们来思考一下第一个桩子
如果它不在橡皮筋上,那它左边肯定得有人帮他撑着呢
但是?没有啊!
末尾的柱子同理,右边没有柱子给他撑着

那我们咋找凸包呢?
我们把凸包用左右两个端点分成两个部分,向上凸叫上凸包,下凸包同理
如何找下凸包?
想象一下下凸包的形状,不难发现这些线段的斜率都是不断上升的
于是我们把每个点入栈,如果发现加入这个点,和之前的点构成的斜率不是递增的,就把上一个点扔了
为什么不把当前点扔了呢?扔了前面的点,目前点可以包含之前的,反之不可以

上凸包对称操作即可

代码:

// Problem: P2742 [USACO5.1]圈奶牛Fencing the Cows /【模板】二维凸包
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2742
// Memory Limit: 128 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#include <bits/extc++.h>
#define INF 0x7fffffff
#define MAXN 100005
#define MAXM 10003
#define eps 1e-9
#define foru(a,b,c)	for(int a=b;a<=c;a++)
#define ford(a,b,c)	for(int a=b;a>=c;a--)
#define RT return 0;
#define db(x)	cout<<endl<<x<<endl;
#define LL long long
#define LXF int
#define RIN rin()
#define HH printf("\n")
using namespace std;
inline LXF rin(){
	LXF x=0,w=1;
	char ch=0;
	while(ch<'0'||ch>'9'){ 
	if(ch=='-') w=-1;
	ch=getchar();
	}
	while(ch>='0'&&ch<='9'){
	x=x*10+(ch-'0');
	ch=getchar();
	}
	return x*w;
}
inline void out(LXF x){
	if(x<0){
	x=-x;
	putchar('-');
	}
	if(x>9) out(x/10);
	putchar(x%10+'0');
}
struct Pos{
	double x,y;
}a[MAXN],s[MAXN];
int n;
double ans;
int top=0;
double dis(Pos p,Pos q){
	return sqrt((q.x-p.x)*(q.x-p.x)+(q.y-p.y)*(q.y-p.y));
}
double getk(Pos p,Pos q){
	return (q.y-p.y)/(q.x-p.x);
}
bool cmp(Pos p,Pos q){
	return p.x!=q.x?p.x<q.x:p.y<q.y;
}
int main(){
	scanf(" %d",&n);
	for(int i=1;i<=n;i++){
		scanf(" %lf %lf",&a[i].x,&a[i].y);
	}
	sort(a+1,a+1+n,cmp);
	for(int i=1;i<=n;i++){
		s[++top]=a[i];
		while(top>=3&&getk(s[top-1],s[top])<getk(s[top-2],s[top-1])){
			top-=2;
			s[++top]=a[i];
		}
	}
	for(int i=2;i<=top;i++){
		ans+=dis(s[i-1],s[i]);
	}
	top=0;
	for(int i=1;i<=n;i++){
		s[++top]=a[i];
		while(top>=3&&getk(s[top-1],s[top])>getk(s[top-2],s[top-1])){
			top-=2;
			s[++top]=a[i];
		}
	}
	for(int i=2;i<=top;i++){
		ans+=dis(s[i-1],s[i]);
	}
	printf("%.2lf",ans);
	return 0;
}
posted @ 2022-08-16 22:56  Cap1taL  阅读(48)  评论(0)    收藏  举报