题目
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; }