UVALive - 7531 Fence

题目链接

分析:
题目要求通过1和 2 长度的边把给定的点全部围起来,于是很容易想到求一个凸包,然后长度1个数为 max(abs(x1x2),abs(y1y2))min(abs(x1x2),abs(y1y2)) , 长度为 2 的为 min(abs(x1x2),abs(y1y2))
需要注意的是叉积会爆int

代码:

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <vector>
#include <queue>
#include <deque>
#include <stack>
#include <set>
#include <cmath>

using namespace std;

struct Point {
    int x, y;
    Point (int x = 0, int y = 0) : x(x), y(y) {}
    bool operator <(const Point &rhs) const {
        if (rhs.x == x) return y < rhs.y;
        return x < rhs.x;
    }
};

typedef Point Vector;

Vector operator +(Vector A, Vector B) {
    return Vector(A.x + B.x, A.y + B.y);
}

Vector operator -(Point A, Point B) {
    return Vector(A.x - B.x, A.y - B.y);
}

long long Cross(Vector A, Vector B) {
    return 1ll * A.x * B.y - 1ll * A.y * B.x;
}

int ConvexHull(Point *p, int n, Point *ch) {
    sort(p, p + n);
    int m = 0;
    for (int i = 0; i < n; i ++) {
        while (m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m --;
        ch[m ++] = p[i];
    }
    int k = m;
    for (int i = n - 2; i >= 0; i --) {
        while (m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m --;
        ch[m ++] = p[i];
    }
    if (n > 1) m --;
    return m;
}

const int maxn = 1e4 + 5;

Point node[maxn], hull[maxn];

long long resa, resb;

void work(const Point &a, const Point &b) {
    int minv = min(abs(a.x - b.x), abs(a.y - b.y));
    int maxv = max(abs(a.x - b.x), abs(a.y - b.y));
    resb += 1ll * minv;
    resa += 1ll * (maxv - minv);
}

int main() {
    int N;
    while (~scanf("%d", &N) && N) {
        resa = 0, resb = 0;
        for (int i = 0; i < N; i++)
            scanf("%d%d", &node[i].x, &node[i].y);

        int len = ConvexHull(node, N, hull);

        for (int i = 1; i < len; i ++) {
//            cout<<hull[i - 1].x<<" "<<hull[i - 1].y<<" "<<hull[i].x<<" "<<hull[i].y<<endl;
            work(hull[i - 1], hull[i]);
        }
        work(hull[0], hull[len - 1]);

        printf("%lld %lld\n", resa, resb);
    }

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值