用每条相邻两点所构成的直线维护一个下凸。
主要注意凸包的点与地面的高度差,地面的拐点与凸包的高度差。
/** * Problem:[JLOI2013]Tower * Author:Shun Yao * Time:2013.5.30 * Result:Accepted */ #include <cstring> #include <cstdlib> #include <cstdio> #include <algorithm> const long Maxn = 305; double abs(double x) { return x < 0 ? -x : x; } long cmp(double x, double y) { if (abs(x - y) < 1e-8) return 0; if (x < y) return -1; return 1; } double min(double x, double y) { return x < y ? x : y; } class pnode { public: double x, y; pnode() {} ~pnode() {} } p[Maxn]; class qnode { public: double k, b, x; qnode() {} ~qnode() {} } q[Maxn], *ql, *qq; bool cmpk(qnode x, qnode y) { return cmp(x.k, y.k) == 0 ? x.b > y.b : x.k < y.k; } bool cmpkk(qnode x, qnode y) { return cmp(x.k, y.k) == 0; } double cross(qnode x, qnode y) { return (x.b - y.b) / (y.k - x.k); } int main() { static long n, i, nn; static double ans; freopen("tower.in", "r", stdin); freopen("tower.out", "w", stdout); scanf("%ld", &n); for (i = 1; i <= n; ++i) scanf("%lf", &p[i].x); for (i = 1; i <= n; ++i) scanf("%lf", &p[i].y); for (i = 1; i < n; ++i) { q[i].k = (p[i].y - p[i + 1].y) / (p[i].x - p[i + 1].x); q[i].b = -q[i].k * p[i].x + p[i].y; } std::sort(ql = q + 1, q + n, cmpk); nn = std::unique(q + 1, q + n, cmpkk) - q; for (qq = ql + 1; qq != q + nn; ++qq) { while (ql > q + 1 && cmp(cross(*qq, *(ql - 1)), (*ql).x) <= 0) --ql; *(++ql) = *qq; (*ql).x = cross(*ql, *(ql - 1)); } i = 1; ans = 1e20; for (qq = q + 1; qq != ql; ++qq) { while (i <= n && cmp(p[i].x, (*(qq + 1)).x) <= 0) { ans = min(ans, abs(p[i].x * (*qq).k + (*qq).b - p[i].y)); ++i; } if (i > n) break; if (i > 1) ans = min(ans, abs((*(qq + 1)).x * (*(qq + 1)).k + (*(qq + 1)).b - ((p[i].y - p[i - 1].y) / (p[i].x - p[i - 1].x) * ((*(qq + 1)).x - p[i].x) + p[i].y))); } while (i <= n) { ans = min(ans, abs(p[i].x * (*qq).k + (*qq).b - p[i].y)); ++i; } printf("%.3lf", ans); fclose(stdin); fclose(stdout); return 0; }