参考博客:点击Here
步骤:
1.先对坐标进行排序,找到最下面的点(y值最小的);
如果有多个,选取横坐标最小的点,将其存入栈中(第一个点)
2.对其他坐标按照极角从小到大进行排序,
极角相同,只留下与P0最远的那个
3.将按极角大小排序后的第一个点存入栈中,
再依次遍历其他点,
如果栈顶俩个元素P1,P2与该点C满足:
P2P1 ✖ P2C > 0 ,说明左转,否则弹出栈顶(右转),
C入栈
4.再用栈顶前俩元素和下一点判断,直到判断完所有点
5.最后计算凸包俩点之间距离求和输出
练习:题目链接
#include<iostream>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
struct node{
int x,y;//存点的坐标
};
const int maxn=1e3+5;
node vex[maxn];//题目给出的坐标
node stackk[maxn];//凸包中所有的点
bool cmp1(node a,node b){//排序找第一个点
if(a.y==b.y){
return a.x<b.x;
}
return a.y<b.y;
}
int cross(node a,node b,node c){//计算叉乘
return (b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
}
double dis(node a,node b){//计算距离
return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
}
bool cmp2(node a,node b){//极角排序 (妙啊!)
int m=cross(vex[0],a,b);
if(m>0)
return 1;
else if(m==0&&(dis(vex[0],a)-dis(vex[0],b)<=0))
return 1;
else
return 0;
}
int main(){
int t;
cin>>t;
for(int i=0;i<t;i++){
cin>>vex[i].x>>vex[i].y;
}
if(t==1){
cout<<0.00<<endl;
}
else if(t==2){
printf("%.2f",dis(vex[0],vex[1]));
}
else{
memset(stackk,0,sizeof(stackk));
sort(vex,vex+t,cmp1);
stackk[0]=vex[0];
sort(vex+1,vex+t,cmp2);
stackk[1]=vex[1];//将排序后的第一个点入栈
int top=1;
for(int i=2;i<t;i++){
while(cross(stackk[top-1],stackk[top],vex[i])<0){//while
--top;
}
stackk[++top]=vex[i];
}
double s=0;//计算凸包周长
for(int i=1;i<=top;i++){
s+=dis(stackk[i-1],stackk[i]);
}
s+=dis(stackk[top],vex[0]);//最后一个点和第一个点之间的距离
printf("%.2lf\n",s);
}
return 0;
}