模板题:洛谷2742二维凸包#include
using namespace std;
const int maxn = 1e5 + 10;
int n;
struct Node{
double x, y;
}p[maxn], s[maxn];
//p是点 s数组模拟栈
//二维向量叉积公式a(x1, y1), b(x2, y2)
//a × b = (x1y2 - x2y1)
double vp(Node a1, Node a2, Node b1, Node b2){
//VectorProduct 向量叉积
return (a2.x-a1.x)*(b2.y-b1.y) - (b2.x-b1.x)*(a2.y-a1.y);
}
double dis(Node a, Node b){
//返回两点距离
return sqrt((b.y-a.y)*(b.y-a.y)+(b.x-a.x)*(b.x-a.x));
}
bool cmp(Node a, Node b)
{
double tmp = vp(p[1], a, p[1], b);
if(tmp > 0) return 1;
//叉积为0 说明两点共线
//让离远点远的点排在靠后的地方
if(tmp == 0 && dis(p[0], a) < dis(p[0], b)) return 1;
return 0;
}//极角排序
int main()
{
scanf("%d", &n);
for(int i = 1; i <= n; i++)
{
scanf("%lf%lf", &p[i].x, &p[i].y);
if(i != 1 && p[i].y < p[1].y) //让p1保存最靠下的点
{
double tmp;
tmp = p[1].y; p[1].y = p[i].y; p[i].y = tmp;
tmp = p[1].x; p[1].x = p[i].x; p[i].x = tmp;
}
}
sort(p+2, p+1+n, cmp);
int cnt = 1; //stack.size()
s[1] = p[1];
for(int i = 2; i <= n; i++)
{
//判断上一个点会不会不合法
while(cnt > 1 && vp(s[cnt-1], s[cnt], s[cnt], p[i]) <= 0)
cnt--;
s[++cnt] = p[i];
}
s[cnt+1] = p[1]; //最后回到起点
//此时栈中存的是所有凸包上的点
double ans = 0;
for(int i = 1; i <= cnt; i++)
ans += dis(s[i], s[i+1]);
printf("%.2f\n", ans);
return 0;
}