Loading

POJ - 3348 Cows 凸包模板题

求凸包的面积

const double pi = acos(-1.0);
const int maxp = 1010;
//`Compares a double to zero`
int sgn(double x) {
    if (fabs(x) < eps)return 0;
    if (x < 0)return -1;
    else return 1;
}

struct Point {
    double x, y;
    Point() {}
    Point(double _x, double _y) {
        x = _x;
        y = _y;
    }
    void input() {
        scanf("%lf%lf", &x, &y);
    }
    bool operator == (Point b)const {
        return sgn(x - b.x) == 0 && sgn(y - b.y) == 0;
    }
    bool operator < (Point b)const {
        return sgn(x - b.x) == 0 ? sgn(y - b.y) < 0 : x < b.x;
    }
    Point operator -(const Point& b)const {
        return Point(x - b.x, y - b.y);
    }
    Point operator +(const Point& b)const {
        return Point(x + b.x, y + b.y);
    }
    Point operator *(const double& k)const {
        return Point(x * k, y * k);
    }
    double distance(Point p) {
        return hypot(x - p.x, y - p.y);
    }
    double operator ^(const Point& b)const {
        return x * b.y - y * b.x;
    }
};


struct polygon {
    int n;
    Point p[maxp];
    void input(int _n) {
        n = _n;
        for (int i = 0; i < n; i++)
            p[i].input();
    }
    void add(Point q) {
        p[n++] = q;
    }
    struct cmp {
        Point p;
        cmp(const Point& p0) { p = p0; }
        bool operator()(const Point& aa, const Point& bb) {
            Point a = aa, b = bb;
            int d = sgn((a - p) ^ (b - p));
            if (d == 0) {
                return sgn(a.distance(p) - b.distance(p)) < 0;
            }
            return d > 0;
        }
    };
    //`进行极角排序`
    //`首先需要找到最左下角的点`
    //`需要重载号好Point的 < 操作符(min函数要用) `
    void norm() {
        Point mi = p[0];
        for (int i = 1; i < n; i++)mi = min(mi, p[i]);
        sort(p, p + n, cmp(mi));
    }
    //`得到凸包`
    //`得到的凸包里面的点编号是0$\sim$n-1的`
    //`两种凸包的方法`
    //`注意如果有影响,要特判下所有点共点,或者共线的特殊情况`
    //`测试 LightOJ1203  LightOJ1239`
    void getconvex(polygon& convex) {
        sort(p, p + n);
        convex.n = n;
        for (int i = 0; i < min(n, 2); i++) {
            convex.p[i] = p[i];
        }
        if (convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;//特判
        if (n <= 2)return;
        int& top = convex.n;
        top = 1;
        for (int i = 2; i < n; i++) {
            while (top && sgn((convex.p[top] - p[i]) ^ (convex.p[top - 1] - p[i])) <= 0)
                top--;
            convex.p[++top] = p[i];
        }
        int temp = top;
        convex.p[++top] = p[n - 2];
        for (int i = n - 3; i >= 0; i--) {
            while (top != temp && sgn((convex.p[top] - p[i]) ^ (convex.p[top - 1] - p[i])) <= 0)
                top--;
            convex.p[++top] = p[i];
        }
        if (convex.n == 2 && (convex.p[0] == convex.p[1]))convex.n--;//特判
        convex.norm();//`原来得到的是顺时针的点,排序后逆时针`
    }
    //`得到面积`
    double getarea() {
        double sum = 0;
        for (int i = 0; i < n; i++) {
            sum += (p[i] ^ p[(i + 1) % n]);
        }
        return fabs(sum) / 2;
    }
};


int main() {
    int n = readint();
    polygon p;
    p.input(n);
    polygon g;
    p.getconvex(g);
    cout << floor(g.getarea() / 50);
}

 

posted @ 2020-08-17 16:05  MQFLLY  阅读(147)  评论(0编辑  收藏  举报