题目:给定一些点,求能把所有这些点包含在内的最小的凸多边形
解法:算法竞赛入门到进阶P283的Andrew算法
(1)把所有这些点按照横坐标从小到大排序,如果x相同,按照y从小到大排序
(2)从左到右扫描所有点,求下凸包。每到达一个点时判断,如果新点在下凸包左前方(向量判断),加入下凸包,否则回溯(删除最近加入的,知道这个新点在下凸包左边,并加入凸包)
(3)同理求上凸包
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
int sgn(double x){
if(fabs(x)<eps)return 0;
else return x<0?-1:1;
}
struct Point{
double x,y;
Point(double X=0,double Y=0){
x=X;
y=Y;
}
Point operator +(Point B){
return Point(x+B.x,y+B.y);
}
Point operator -(Point B){
return Point(x-B.x,y-B.y);
}
Point operator *(double k){
return Point(x*k,y*k);
}
Point operator /(double k){
return Point(x/k,y/k);
}
bool operator ==(Point B){
return sgn(x-B.x)==0&&sgn(y-B.y)==0;
}
bool operator <(Point B){
return sgn(x-B.x)<0||(sgn(x-B.x)==0&&sgn(y-B.y<0));
}
};
typedef Point Vector;
double Cross(Vector A,Vector B){
return A.x*B.y-A.y*B.x;
}
double Distance(Point A,Point B){
return hypot(A.x-B.x,A.y-B.y);
}
int Convex_hull(Point *p,int n,Point *ch){
sort(p,p+n);
n=unique(p,p+n)-p;
int v=0;
for(int i=0;i<n;i++){
while(v>1&&sgn(Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]))<=0)
v--;
ch[v++]=p[i];
}
int j=v;
for(int i=n-2;i>=0;i--){
while(v>j&&sgn(Cross(ch[v-1]-ch[v-2],p[i]-ch[v-2]))<=0)
v--;
ch[v++]=p[i];
}
if(n>1)v--;
return v;
}
Point p[11000],ch[11000];
int main(){
int n;
cin>>n;
for(int i=0;i<n;i++)
cin>>p[i].x>>p[i].y;
int v=Convex_hull(p,n,ch);
double ans=0;
if(v==1)ans=0;
else if(v==2)ans=Distance(ch[0],ch[1]);
else{
for(int i=0;i<v;i++)
ans+=Distance(ch[i],ch[(i+1)%v]);
printf("%.2lf\n",ans);
}
return 0;
}