何为凸包
凸包也就是类似求这样一个东西:
给出一个点集,先在需要找出能围住所有点的一个周长最小的最小凸多边形。也就相当于选出位于最外层的点,将他们连接起来。
注意凸包是不可能凹的,因为存在一个凹口时,可以连接两边的点,反而让周长更小了
凸包的求解
求解凸包一般使用(Andrew)算法
此算法的大致过程如下:
将所有点按(x)坐标从小到大排序,并以(y)为第二关键字从小到大排序。然后先做下凸包,上凸包类似
下凸包的做法是:先将前两个点入栈,然后扫描,每次碰到当前点位于向量((top-1,top))下方时就(pop),直到可以保证凸(不凹)为止
如何判断一个点在一个向量下方?用叉积即可。由于叉积是乘(sin)的,所以叉积的正负就取决于角度的正负
时间复杂度:(O(nlogn+2n))
代码如下
/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
#include <cmath>
#define r read()
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 1061109567;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){
int x = 0; int w = 1; register char c = getchar();
for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());
if(c == '-') w = -1, c = getchar();
for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
int N;
struct Coordinate{
double x, y;
};
Coordinate a[MAXN];
double ans;
int top,sta[MAXN];
inline bool cmp(const Coordinate& a, const Coordinate& b){
if(a.x != b.x) return a.x < b.x;
return a.y < b.y;
}
inline double sqr(const double _X){
return _X * _X;
}
inline double dist(int _a, int _b){
double x1 = a[_a].x, y1 = a[_a].y;
double x2 = a[_b].x, y2 = a[_b].y;
return sqrt(sqr(x1-x2)+sqr(y1-y2));
}
inline double Cross(int _a, int _b, int _c){
double x1 = a[_b].x-a[_a].x, y1 = a[_b].y-a[_a].y;
double x2 = a[_c].x-a[_a].x, y2 = a[_c].y-a[_a].y;
return x1*y2 - x2*y1;
}
inline void ConvexHull(){
sort(a+1, a+N+1, cmp);
top = 2;
sta[1] = 1, sta[2] = 2;
ans = dist(sta[1], sta[2]);
for(int i = 3; i <= N; ++i){
while(top > 1 && Cross(sta[top-1],i,sta[top]) > 0){
ans -= dist(sta[top-1], sta[top]);
--top;
}
ans += dist(sta[top],i);
sta[++top] = i;
}
top = 2;
sta[1] = N, sta[2] = N-1;
ans += dist(sta[1], sta[2]);
for(int i = N-2; i > 0; --i){
while(top > 1 && Cross(sta[top-1],i,sta[top]) > 0){
ans -= dist(sta[top-1], sta[top]);
--top;
}
ans += dist(sta[top],i);
sta[++top] = i;
}
}
int main(){
scanf("%d", &N);
for(int i = 1; i <= N; ++i){
scanf("%lf %lf", &a[i].x, &a[i].y);
}
ConvexHull();
printf("%.2f", ans);
return 0;
}