HDU 5130 & 5134 2014ICPC廣州現場賽 D & H (計算幾何)
阿新 • • 發佈:2018-11-10
D - Signal Interference
給定一個多邊形及其內部的點A,並給出另一個點B,求多邊形內部到B距離不超過到A距離的k倍的點集的面積。
經過推導可以得出來滿足距離關係的點集是一個圓,那麼就只需要求出這個圓之後求它與這個多邊形的面積交即可。
H - Highway
某個人在距離高速公路D的點處,他在公路外的速度是v0, 公路上的速度是v1,求在時間T內能走到的區域的面積。
對於高速公路兩側的一個點,顯然最快的方式是:
對於第一次到達高速公路的這個點,我們可以通過三分的方法來求出它。
這樣實際的範圍就是:
答案即為圓與這個六邊形的面積交。六邊形兩端的頂點可以通過高速公路上最遠的距離求出。圓的半徑就是路外速度能走的最遠距離。
不是很懂這是什麼操作……一場區域賽兩個計算幾何都是圓與多邊形面積交……很是奇葩……
H題:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; const double eps = 1e-8; const double pi = acos(-1.0); int sgn(double x) { if(fabs(x) < eps) return 0; if(x < 0) return -1; return 1; } struct point { double x, y; point (){} point (double _x, double _y) { x = _x; y = _y; } point operator - (const point &o) const { return point(x - o.x, y - o.y); } point operator + (const point &o) const { return point(x + o.x, y + o.y); } double operator ^ (const point &o) const { return x*o.y - y*o.x; } double operator * (const point &o) const { return x*o.x + y*o.y; } point operator * (const double &o) const { return point(x*o, y*o); } point operator / (const double &o) const { return point(x/o, y/o); } double dis(point o) { return sqrt((x-o.x)*(x-o.x) + (y-o.y)*(y-o.y)); } double rad(point a, point b) { point p = *this; return fabs(atan2(fabs((a-p)^(b-p)), (a-p)*(b-p))); } double len2() { return x*x + y*y; } point trunc(double r) { double l = sqrt(x*x + y*y); if(!sgn(l)) return *this; r /= l; return point(x*r, y*r); } }A, B; struct Line { point s, e; Line (){} Line (point _s, point _e) { s = _s; e = _e; } point lineprog(point p) { return s + (((e-s)*((e-s)*(p-s)))/((e-s).len2())); } double dispointtoline(point p) { return fabs((p-s)^(e-s))/(s.dis(e)); } }; struct circle { point p; double r; circle (){} circle (point _p, double _r) { p = _p; r = _r; } int relation(point b) { double dst = b.dis(p); if(sgn(dst - r) < 0) return 2; else if(sgn(dst - r) == 0) return 1; return 0; } int relationline(Line v) { double dst = v.dispointtoline(p); if(sgn(dst - r) < 0) return 2; else if(sgn(dst - r) == 0) return 1; return 0; } int pointcrossline(Line v, point &p1, point &p2) { if(!(*this).relationline(v)) return 0; point a = v.lineprog(p); double d = v.dispointtoline(p); d = sqrt(r*r - d*d); if(sgn(d) == 0) { p1 = a; p2 = a; return 1; } p1 = a + (v.e - v.s).trunc(d); p2 = a - (v.e - v.s).trunc(d); return 2; } double areatan(point a, point b) { if(sgn((p-a)^(p-b)) == 0) return 0.0; point q[5]; int len = 0; q[len++] = a; Line l(a, b); point p1, p2; if(pointcrossline(l, q[1], q[2]) == 2) { if(sgn((a-q[1])*(b-q[1]))< 0)q[len++] = q[1]; if(sgn((a-q[2])*(b-q[2]))< 0)q[len++] = q[2]; } q[len++] = b; if(len == 4 && sgn((q[0]-q[1])*(q[2]-q[1])) > 0) swap(q[1], q[2]); double res = 0; for(int i = 0;i < len-1;i++) { if(relation(q[i]) == 0 || relation(q[i+1]) == 0) { double arg = p.rad(q[i], q[i+1]); res += r*r*arg/2.0; } else res += fabs((q[i]-p)^(q[i+1]-p))/2.0; } return res; } }; struct polygon { int n; point p[505]; double areacircle(circle c) { double ans = 0; for(int i = 0;i < n;i++) { int j = (i+1) % n; if(sgn((p[j]-c.p)^(p[i]-c.p)) >= 0) ans += c.areatan(p[i], p[j]); else ans -= c.areatan(p[i], p[j]); } return fabs(ans); } }POL; double v0, v1, D, T; double fun(double x) { return sqrt(v0*x*v0*x - D*D) + v1*(T - x); } int main() { int kase = 0; while(scanf("%lf%lf%lf%lf", &v0, &v1, &D, &T) != EOF) { POL.n = 6; circle C; C.p.x = 0, C.p.y = D, C.r = v0*T; double L = D/v0, R = T, mid, mmid; for(int i = 1;i <= 100;i++) { mid = (L + R)/2; mmid = (mid + R)/2; double fa = fun(mid), fb = fun(mmid); if(fa > fb) R = mmid; else L = mid; } double t = (L + R)/2; double x = fun(t); double ya = T/t*D, xa = sqrt(v0*T*v0*T - ya*ya); ya -= D; POL.p[0] = point(x, 0); POL.p[1] = point(xa, ya); POL.p[2] = point(-xa, ya); POL.p[3] = point(-x, 0); POL.p[4] = point(-xa, -ya); POL.p[5] = point(xa, -ya); double ans = pi*v0*T*v0*T + xa*ya*4 + ya*(x - xa)*2; ans -= POL.areacircle(C); if(v0*T <= D) ans = pi*v0*T*v0*T; printf("Case %d: %.8lf\n", ++kase, ans); } return 0; }