[HDU 4697 Convex hull] 动态凸包面积积分

题目

http://acm.hdu.edu.cn/showproblem.php?pid=4697

分析

凸包+积分

首先要发现动态凸包上的点发生变化的分界点是三点共线的时候,所以把这些时间点处理出来

排序,之后每一区间内找出这段区间内的凸包上的点,然后对差积积分即可

代码

/**************************************************
 *        Problem:  HDU 4697
 *         Author:  clavichord93
 *          State:  Accepted
 **************************************************/

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
const double EPS = 1e-12;


const int MAX_N = 55;


inline int sgn(double a) {
    return a > EPS ? 1 : (a < -EPS ? -1 : 0);
}


struct Point {
    double x, y;
    int id;
    Point() { x = y = 0; }
    Point(double _x, double _y) : x(_x), y(_y) {}
    Point operator + (const Point &a) const {
        return Point(x + a.x, y + a.y);
    }
    Point operator - (const Point &a) const {
        return Point(x - a.x, y - a.y);
    }
    Point operator * (const double &k) const {
        return Point(x * k, y * k);
    }
    Point operator / (const double &k) const {
        return Point(x / k, y / k);
    }
    Point& operator = (const Point &a) {
        x = a.x, y = a.y;
        id = a.id;
        return *this;
    }
    bool operator < (const Point &a) const {
        return sgn(x - a.x) < 0 || (!sgn(x - a.x) && sgn(y - a.y) < 0);
    }
    bool operator == (const Point &a) const{
        return !sgn(x - a.x) && !sgn(y - a.y);
    }
    bool operator != (const Point &a) const {
        return sgn(x - a.x) || sgn(y - a.y);
    }
    //法向量,左手方向
    Point normal() const {
        return Point(-y, x);
    }
    void read() {
        scanf("%lf %lf", &x, &y);
    }
    void print() {
        printf("%.6f %.6f\n", x, y);
    }
};
typedef Point Vector;


inline double det(const Point &a, const Point &b, const Point &c) {
    return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}


inline double det(const Vector &a, const Vector &b) {
    return a.x * b.y - b.x * a.y;
}


int n;
double limit;
Point p[MAX_N];
Vector v[MAX_N];


Point q[MAX_N];
Point poly[MAX_N];
Point s[MAX_N];


int cntEvent;
double event[MAX_N * MAX_N * MAX_N * 2];


int convexHull(Point *poly, int n, Point *goal) {
    int m = 0;
    sort(poly, poly + n);
    for (int i = 0; i < n; i++) {
        if (!i || poly[i] != poly[i - 1]) {
            goal[m++] = poly[i];
        }
    }
    int top = 0;
    for (int i = 0; i < m; i++) {
        while (top > 1 && det(s[top - 2], s[top - 1], goal[i]) >= 0) {
            top--;
        }
        s[top++] = goal[i];
    }
    int k = top;
    for (int i = m - 1; i >= 0; i--) {
        while (top > k && det(s[top - 2], s[top - 1], goal[i]) >= 0) {
            top--;
        }
        s[top++] = goal[i];
    }
    top--;
    for (int i = 0; i < top; i++) {
        goal[i] = s[i];
    }
    return top;
}


double f(double A, double B, double C, double x) {
    return A * x * x * x / 3 + B * x * x / 2 + C * x;
}


int main() {
    #ifdef LOCAL_JUDGE
    freopen("in.txt", "r", stdin);
    freopen("out.txt", "w", stdout);
    #endif
    while (scanf("%d %lf", &n, &limit) != EOF) {
        for (int i = 0; i < n; i++) {
            p[i].read();
            v[i].read();
        }


        cntEvent = 0;
        event[cntEvent++] = 0;
        event[cntEvent++] = limit;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                for (int k = j + 1; k < n; k++) {
                    Point p1 = p[j] - p[i];
                    Vector v1 = v[j] - v[i];
                    Point p2 = p[k] - p[i];
                    Vector v2 = v[k] - v[i];


                    double A = det(v1, v2);
                    double B = det(p1, v2) + det(v1, p2);
                    double C = det(p1, p2);


                    if (!sgn(A)) {
                        if (sgn(B)) {
                            double t = -C / B;
                            if (sgn(t) > 0 && sgn(t - limit) < 0) {
                                event[cntEvent++] = t;
                            }
                        }
                    }
                    else {
                        double delta = B * B - 4.0 * A * C;
                        if (sgn(delta) >= 0) {
                            double t1 = (-B + sqrt(delta)) / (2.0 * A);
                            double t2 = (-B - sqrt(delta)) / (2.0 * A);
                            if (sgn(t1) > 0 && sgn(t1 -  limit) < 0) {
                                event[cntEvent++] = t1;
                            }
                            if (sgn(t2) > 0 && sgn(t2 -  limit) < 0) {
                                event[cntEvent++] = t2;
                            }
                        }
                    }
                }
            }
        }


        sort(event, event + cntEvent);
        cntEvent = unique(event, event + cntEvent) - event;


        //printf("%d\n", cntEvent);
        //for (int i = 0; i < cntEvent; i++) {
            //printf("%.6f ", event[i]);
        //}
        //printf("\n");


        double ans = 0;
        for (int i = 0; i < cntEvent - 1; i++) {
            double t = 0.5 * (event[i] + event[i + 1]);
            for (int j = 0; j < n; j++) {
                q[j] = p[j] + v[j] * t;
                q[j].id = j;
            }
            int size = convexHull(q, n, poly);
            //printf("%d\n", size);
            //for (int j = 0; j < size; j++) {
                //poly[j].print();
            //}
            if (size >= 3) {
                double res = 0;
                for (int j = 0; j < size; j++) {
                    double A = det(v[poly[j].id], v[poly[((j + 1) % size) % size].id]);
                    double B = det(p[poly[j].id], v[poly[(j + 1) % size].id]) + det(v[poly[j].id], p[poly[(j + 1) % size].id]);
                    double C = det(p[poly[j].id], p[poly[(j + 1) % size].id]);
                    res += f(A, B, C, event[i + 1]) - f(A, B, C, event[i]);
                }
                ans += 0.5 * fabs(res);
            }
        }


        printf("%.10f\n", ans / limit);
    }


    return 0;
}


你可能感兴趣的:([HDU 4697 Convex hull] 动态凸包面积积分)