首页 > 其他分享 >二维凸包

二维凸包

时间:2023-02-09 19:23:28浏览次数:32  
标签:cnt cor return double cross 凸包 二维 y1

Andrew算法

时间复杂度\(O(nlogn)\)
把所有点以横坐标为第一关键字排序,纵坐标为第二关键字
最小的元素和最大的元素一定在凸包上
从第一个点开始遍历,如果下一个点在栈顶的两个元素所连成直线的左边,那么就入栈
否则如果在右边,说明凸包有更优的方案,上次的点出栈,
并直到新点在栈顶两个点所在的直线的左边为止
至于判断左边还是右边,用叉积

#include <bits/stdc++.h>
using namespace std;

const int N=2e5+100;

struct cor {

	double x,y;

}a[N],b[N];

double dist(cor p,cor q) {
	double A=p.x-q.x,B=p.y-q.y;
	return sqrt(A*A+B*B);
}

double cross(cor p,cor r,cor q) {
	double x1=p.x-r.x,y1=p.y-r.y;
	double x2=q.x-r.x,y2=q.y-r.y;
	return (x1*y2)-(x2*y1);
}

bool cmp(cor p,cor q) {
	if(p.x==q.x) return p.y<q.y;
	return p.x<q.x;
}

int n,cnt=0;
double ans=0; 
void Andrew() {
	
	sort(a+1,a+n+1,cmp);
	b[++cnt]=a[1];
	for(int i=2;i<=n;i++) {
		
		while(cnt>1&&cross(b[cnt],b[cnt-1],a[i])<=0) cnt--;
		b[++cnt]=a[i];
		
	}
	int t=cnt;
	for(int i=n-1;i>=1;i--) {
		
		while(cnt>t&&cross(b[cnt],b[cnt-1],a[i])<=0) cnt--;
		b[++cnt]=a[i];
		
	}
	
}

int main() {
	
	scanf("%d",&n);
	for(int i=1;i<=n;i++) {
		scanf("%lf%lf",&a[i].x,&a[i].y);
	}
	Andrew();
	for(int i=1;i<cnt;i++) ans+=dist(b[i],b[i+1]);
	ans+=dist(b[cnt],b[1]);
	printf("%.2lf\n",ans);

	return 0;
}

标签:cnt,cor,return,double,cross,凸包,二维,y1
From: https://www.cnblogs.com/Diamondan/p/17106759.html

相关文章