UVALive 6859 (凸包)

本文介绍了一种通过将每个点拆分为四个方向的点并利用这些点构造凸包的方法。通过对比坐标差值来处理特定长度的边,给出了完整的C++实现代码。

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

将每个点分成上下左右四个点加入图中,求出凸包,由于只有长度为sqrt(2.0)和1的边,所以按照横坐标差值和纵坐标差值处理即可,代码如下:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <vector>
using namespace std;
typedef long long LL;
const int maxn = 400007;
double EPS = 1e-10;

double add(double a, double b) {
    if(abs(a+b) < EPS * (abs(a)+abs(b))) return 0;
    return a+b;
}

struct P {
    double x, y;
    P() {}
    P(double x, double y) : x(x), y(y) {}
    P operator + (P p) { return P(add(x, p.x), add(y, p.y)); }
    P operator - (P p) { return P(add(x,-p.x), add(y,-p.y)); }
    P operator * (double d) { return P(x*d, y*d); }
    double dot(P p) { return add(x*p.x, y*p.y); }
    double det(P p) { return add(x*p.y, -y*p.x); }
};

bool cmp_x(const P& p, const P& q) {
    if(p.x != q.x) return p.x < q.x;
    return p.y < q.y;
}

vector<P> convex_hull(P* ps, int n) {
    sort(ps, ps+n, cmp_x);
    int k = 0;
    vector<P> qs(n*2);

    for(int i = 0; i < n; ++i) {
        while(k > 1 && (qs[k-1]- qs[k-2]).det(ps[i] - qs[k-1]) <= 0 ) k--;
        qs[k++] = ps[i];
    }

    for(int i = n-2, t = k; i >= 0; --i) {
        while(k > t && (qs[k-1] - qs[k-2]).det(ps[i]-qs[k-1]) <= 0) k--;
        qs[k++] = ps[i];
    }
    qs.resize(k-1);
    return qs;
}

double dist(P p, P q) {
    return (p-q).dot(p-q);
}

int N;
P ps[maxn];

void solve(int n) {
    vector<P> qs = convex_hull(ps, n);
    double res = 0.0;
    int kk = qs.size();
    double two = sqrt(2.0);
    for(int i = 0; i < kk; ++i) {
        int t1 = abs(qs[i].x-qs[(i-1+kk)%kk].x), t2 = abs(qs[i].y-qs[(i-1+kk)%kk].y);
        res += abs(t1-t2);
        res += (double)1.0*min(t1, t2)*two;
    }
    printf("%.5lf\n", res);
}

int main() {
    int n;
    while(~scanf("%d", &n)) {
        int cnt = 0;
        for(int i = 0; i < n; ++i) {
            double x, y; scanf("%lf%lf", &x, &y);
            ps[cnt].x = x+1;
            ps[cnt++].y = y;

            ps[cnt].x = x;
            ps[cnt++].y = y+1;

            ps[cnt].x = x-1;
            ps[cnt++].y = y;

            ps[cnt].x = x;
            ps[cnt++].y = y-1;
        }
        solve(cnt);
    }


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

JalexDooo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值