[学习笔记] 凸包
凸包
由于
我们把输入按照
叉积
求凸包时用到了叉积,叉积有一个右手定则。
形象地说就是假设手在求叉积的面上(一条线和不在线上的一点确定一个平面,所以平面一定存在)手指指向栈最后一个点,大拇指向上为正,向下为负。
另外点在直线上时叉积为
code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
using namespace std;
int n;
int stu[100010],tot;
bool v[100010];
double ans;
struct node{
double x,y;
}a[100010];
bool cmp(node x,node y){
if(x.x!=y.x) return x.x<y.x;
return x.y<y.y;
}
bool check(){
double a1=a[stu[tot]].x-a[stu[tot-2]].x;
double b1=a[stu[tot]].y-a[stu[tot-2]].y;
double a2=a[stu[tot-1]].x-a[stu[tot-2]].x;
double b2=a[stu[tot-1]].y-a[stu[tot-2]].y;
double an=(a1*b2)-(a2*b1);
if(an>=0) return 0;
return 1;
}
double dis(int x,int y){
return sqrt((a[x].x-a[y].x)*(a[x].x-a[y].x)+(a[x].y-a[y].y)*(a[x].y-a[y].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+n+1,cmp);
stu[++tot]=1;
stu[++tot]=2;
for(int i=3;i<=n;i++){
stu[++tot]=i;
while(tot!=2&&!check()){
stu[tot-1]=stu[tot];
tot--;
}
}
for(int i=2;i<=tot;i++){
ans+=dis(stu[i],stu[i-1]);
v[stu[i]]=1;
}
tot=0;
stu[++tot]=n;
stu[++tot]=n-1;
for(int i=n-2;i>=1;i--){
if(v[i]) continue;
stu[++tot]=i;
while(tot!=2&&!check()){
stu[tot-1]=stu[tot];
tot--;
}
}
for(int i=2;i<=tot;i++){
ans+=dis(stu[i],stu[i-1]);
}
printf("%.2lf",ans);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】