- Graham扫描法
- 向量的叉乘:平行四边形面积,顺负逆正,x1y2-x2y1
1.确定1个凸包上的点:纵坐标最小(纵坐标相同时横坐标最小)的点
2.极角排序
3.单调栈维护凸包
点击查看代码
//二维凸包
#include <bits/stdc++.h>
using namespace std;
struct t1
{
double x,y;
}t[100005];
int s[100005];
double c(t1 a,t1 b)
{
return a.x*b.y-a.y*b.x;
}
double d(t1 a,t1 b)
{
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp(t1 a,t1 b)
{
t1 tmpa,tmpb;
tmpa.x=a.x-t[1].x;
tmpa.y=a.y-t[1].y;
tmpb.x=b.x-t[1].x;
tmpb.y=b.y-t[1].y;
double tmp=c(tmpa,tmpb);
if(tmp>0||tmp==0&&d(t[1],a)<d(t[1],b))
{
return true;
}
return false;
}
int main()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
scanf("%lf%lf",&t[i].x,&t[i].y);
if(t[i].y<t[1].y||t[i].y==t[1].y&&t[i].x<t[1].x)
{
swap(t[i],t[1]);
}
}
sort(t+2,t+n+1,cmp);
int cnt=1;
s[1]=1;
for(int i=2;i<=n;i++)
{
while(cnt>1)
{
t1 h1=t[s[cnt]],h2=t[s[cnt-1]];
t1 tmp1,tmp2;
tmp1.x=t[i].x-h2.x;
tmp1.y=t[i].y-h2.y;
tmp2.x=h1.x-h2.x;
tmp2.y=h1.y-h2.y;
if(c(tmp1,tmp2)>=0)
{
cnt--;
}
else
{
break;
}
}
cnt++;
s[cnt]=i;
}
cnt++;
s[cnt]=1;
double ans=0;
for(int i=1;i<cnt;i++)
{
ans+=d(t[s[i]],t[s[i+1]]);
}
cout<<fixed<<setprecision(2)<<ans<<endl;
return 0;
}