POJ 3334 - Connected Gheeves
http://poj.org/problem?id=3334
概要
Gheeves とは,以下の条件を満たす点列 (p[1], ..., p[n]) を直線で結んでできる漏斗のような形をしたものである. 図があるのでイメージしやすい.
- 3 <= n <= 1000
- y[1] > y[2] > ... > y[c] かつ y[c] < y[c+1] < ... < y[n] となる 1 < c < n が存在する
- 任意の 1 <= i < c なる i について x[i] < x[c]
- 任意の c < i <= n なる i について x[i] > x[c]
- 任意の 1 <= i < c なる i について,p[i-1], p[i], p[i+1] が同一直線上になるように p[i-1] を p[i] に関して時計回りに回転させたときの角度は180度より大きい
- 同様に,任意の c < i < n なる i について,p[i-1], p[i], p[i+1] が同一直線上になるように p[i-1] を p[i] に関して時計回りに回転させたときの角度は180度より大きい
x 座標がすべて負の gheeves P と,x 座標がすべて正の gheeves Q が与えられる. この2つの gheeves は,太さの無視できる管で底が繋がっている.
これに容量 A の水を入れたときの,水位の y 座標を答える. 今は二次元上で考えているので,面積が容量に等しい.
ただし,もし水位がいずれかの gheeves のへりより高くなった場合,そこから水はこぼれ落ちる.
制約
上の gheeves の定義にある通り
制約
水位 h に関して,そのときの容量を計算して二分探索.
線分 pq に対して,pq が h より低ければ台形,pq と h が交わっていれば三角形を足していくことで容量を求める.
poj/3334.cc1 #include <cstdio> 2 #include <vector> 3 #include <complex> 4 using namespace std; 5 typedef complex<double> P; 6 static const double EPS = 1e-6; 7 8 inline double cross(const P& a, const P& b) { return a.real()*b.imag() - b.real()*a.imag(); } 9 10 struct line 11 { 12 P a, b; 13 line() {} 14 line(const P& p, const P& q) : a(p), b(q) {} 15 }; 16 17 struct segment 18 { 19 P a, b; 20 segment() {} 21 segment(const P& x, const P& y) : a(x), b(y) {} 22 23 inline bool intersects(const line& ln) const 24 { 25 return cross(ln.b - ln.a, a - ln.a) * cross(ln.b - ln.a, b - ln.a) < EPS; 26 } 27 28 inline P intersection(const line& ln) const 29 { 30 const P x = b - a; 31 const P y = ln.b - ln.a; 32 return a + x*(cross(y, ln.a - a))/cross(y, x); 33 } 34 }; 35 36 double area(const vector<segment> *ps, double h) 37 { 38 double s = 0.0; 39 const line ln(P(0, h), P(1, h)); 40 for (int i = 0; i < 2; i++) { 41 for (vector<segment>::const_iterator it = ps[i].begin(); it != ps[i].end(); ++it) { 42 P a = it->a, b = it->b; 43 if (a.imag() < b.imag()) { 44 swap(a, b); 45 } 46 47 if (a.imag() <= h) { 48 s += (h - a.imag() + h - b.imag()) * fabs(a.real() - b.real()) / 2.0; 49 } else if (it->intersects(ln)) { 50 const P p = it->intersection(ln); 51 s += fabs(p.real() - b.real()) * (p.imag() - b.imag()) / 2.0; 52 } 53 } 54 } 55 return s; 56 } 57 58 int main() 59 { 60 int T; 61 scanf("%d", &T); 62 while (T-- > 0) { 63 int A; 64 scanf("%d", &A); 65 vector<segment> ps[2]; 66 double left = 1e10; 67 for (int i = 0; i < 2; i++) { 68 int k; 69 scanf("%d", &k); 70 P prev; 71 for (int j = 0; j < k; j++) { 72 int x, y; 73 scanf("%d %d", &x, &y); 74 left = min(left, double(y)); 75 if (j != 0) { 76 ps[i].push_back(segment(prev, P(x, y))); 77 } 78 prev = P(x, y); 79 } 80 } 81 double right = min(min(ps[0].front().a.imag(), ps[0].back().b.imag()), min(ps[1].front().a.imag(), ps[1].back().b.imag())); 82 for (int i = 0; i < 100; i++) { 83 const double mid = (left + right)/2.0; 84 const double s = area(ps, mid); 85 if (s < A) { 86 left = mid; 87 } else { 88 right = mid; 89 } 90 } 91 printf("%.3f\n", (left + right)/2.0); 92 } 93 return 0; 94 }