hdu1392(凸包求周长)

本文介绍了一个经典的几何问题——凸包问题,并提供了一种基于Gramham算法的解决方案。通过使用kuangbin的模板,文章详细解释了如何计算一组点围成的最小凸多边形的周长,特别注意了特殊情况的处理。

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

题目链接:Surround the Trees

题目大意:给出一些点,用直线将这些点包围起来,求直线的最小长度

分析:裸的凸包,用了kuangbin的模板,其中Gramham算法的实现和网上的讲解有些不用

网上似乎都是求的

cross(plist[pstack[top]], plist[pstack[top-1]], plist[i])

kuangbin用的是

cross(plist[pstack[top-1]], plist[pstack[top]], plist[i])
不过殊途同归


注意:

n=1和n=2的情况,直接套用kuangbin的模板,当n=2时,

for (int i = 1; i <=top; i++){
            res += dis(plist[pstack[i - 1]], plist[pstack[i]]);
        }
        res += dis(plist[pstack[top]], plist[0]);
会导致一条线段算了两遍

#include <stdio.h>
#include <math.h>
#include <algorithm>

using namespace std;

const int maxn = 1005;

struct point
{
    double x, y;
}plist[maxn];
int pstack[maxn], top;

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

double dis(const point &p1, const point &p2)
{
    return sqrt((p2.x - p1.x)*(p2.x - p1.x) + (p2.y - p1.y)*(p2.y - p1.y));
}

bool cmp(const point &p1, const point &p2)
{
    double tmp = cross(plist[0], p1, p2);
    if (tmp > 0.0)return true;
    else if (tmp == 0.0 && dis(plist[0], p1) < dis(plist[0], p2))return true;
    else return false;
}


void Graham(int n)
{
    
    top = 1;
    pstack[0] = 0;
    pstack[1] = 1;
    for (int i = 2; i < n; i++){
        while (top>0 && cross(plist[pstack[top - 1]], plist[pstack[top]], plist[i]) <= 0)top--;
        pstack[++top] = i;
    }

}

int main()
{
    //freopen("in.txt", "r", stdin);
    int n;
    double res;
    while (scanf("%d", &n) != EOF&&n){
        res = 0;
        int k = 0;
        scanf("%lf %lf", &plist[0].x, &plist[0].y);
        point p0 = plist[0];
        for (int i = 1; i < n; i++){
            scanf("%lf %lf", &plist[i].x, &plist[i].y);
            if (p0.y > plist[i].y || (p0.y == plist[i].y&&p0.x > plist[i].x)){
                p0.x = plist[i].x;
                p0.y = plist[i].y;
                k = i;
            }
        }

        plist[k] = plist[0];
        plist[0] = p0;

        if (n == 1)
        {
            printf("0.00\n");
            continue;
        }
        else if (n == 2)
        {
            printf("%.2lf\n", dis(plist[0], plist[1]));
            continue;
        }

        sort(plist + 1, plist + n, cmp);
        Graham(n);
        for (int i = 1; i <=top; i++){
            res += dis(plist[pstack[i - 1]], plist[pstack[i]]);
        }
        res += dis(plist[pstack[top]], plist[0]);
        printf("%.2lf\n", res);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值