php 凸包排序,二维凸包学习笔记

模板题:洛谷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;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值