凸包graham模板题-poj3348

本文介绍了一种基于格拉姆扫描算法实现凸包构造的方法。通过定义点之间的距离和交叉乘积,对输入点集进行排序并使用栈来去除不必要的点,最终形成凸包。该算法首先找到坐标最小的点作为起点,然后根据其余点与起点形成的向量角度进行排序,最后通过栈操作确定凸包上的点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

a×b
a与b夹角小于180度(逆时针),那么这个值就是正值,大于180度就是负值



#include <cstdio>
#include <algorithm>

using namespace std;

const int maxn = 10001;

typedef struct point
{
    int x, y;
}point;

point p[maxn];

int s1[maxn];
int cnt;

int n;

int dist(point a, point b)
{
    return (a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);
}

int cross(point p0, point p1, point p2)
{
    return (p1.x-p0.x)*(p2.y-p0.y)-(p1.y-p0.y)*(p2.x-p0.x);
}

bool cmp(point a, point b)
{
    int tmp = cross(p[0], a, b);
    if(tmp != 0) return tmp > 0;
    return dist(p[0], a) <= dist(p[0], b);
}

void graham();
int darea(point m, point n);         //每个小三角形的两倍
int dsumarea();

int main()
{
    int i;
    int pos = 0;
    while(~scanf("%d", &n))
    {
        for(i = 0; i < n; ++i)          //保证p[0]的y,x最小
        {
            scanf("%d %d", &p[i].x, &p[i].y);
            if(p[i].y < p[pos].y || (p[i].y == p[pos].y && p[i].x < p[pos].x))
                pos = i;
        }
        swap(p[0], p[pos]);
        graham();
        int ans = dsumarea() / (50 * 2);
        printf("%d\n", ans);
    }
    return 0;
}

int darea(point m, point n)         //每个小三角形的两倍
{
    return (m.x-p[0].x)*(n.y-p[0].y)-(m.y-p[0].y)*(n.x-p[0].x);
}

int dsumarea()        //总面积的两倍
{
    int i, j;
    int sum = 0;
    for(i = 1; i < cnt - 1; ++i)
    {
        sum += darea(p[s1[i]], p[s1[i + 1]]);
    }
    return sum;
}

void graham()
{
    int i;
    //找到(x, y)最小的点
    cnt = 0;
    sort(p + 1, p + n, cmp);
    s1[cnt++] = 0;
    s1[cnt++] = 1;
    for(i = 2; i < n; ++i)
    {
        while(cross(p[s1[cnt - 2]], p[s1[cnt - 1]], p[i]) < 0) --cnt;
        s1[cnt++] = i;
    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值