POJ 1266 - Cover an Arc.
http://poj.org/problem?id=1266
概要
二次元座標上に弧の両端点と内点が与えられる. この弧を長方形のカーペットで覆いたい. そのときの長方形の面積を答える.
ただし,カーペットの縦および横の長さは整数値で,それぞれ軸に平行な向きで,カーペットの端の座標も整数値とする.
制約
- 弧は [-1000, 1000] × [-1000, 1000] の正方形の範囲に収まっている
解法
まず弧の中心 O を求めて,O を中心とした円の上下左右の座標を計算し,弧の上にあったらその座標,なかったら弧の端点の座標を採用する,というかんじにすれば,弧の最大・最小のx座標・y座標を求められる.
円周上のある点 P が弧の上に乗っているかどうかは,片方の端点を基準に,端点と内点の位置関係(外積)と,端点と P の位置関係が同じかどうかで判定する.
poj/1266.cc1 #include <iostream> 2 #include <complex> 3 #include <cmath> 4 using namespace std; 5 typedef complex<double> P; 6 7 inline double cross(const P& a, const P& b) 8 { 9 return a.real()*b.imag() - b.real()*a.imag(); 10 } 11 12 struct line 13 { 14 P a, b; 15 line(const P& x, const P& y) : a(x), b(y) {} 16 17 inline P intersection(const line& ln) const 18 { 19 const P x = b - a; 20 const P y = ln.b - ln.a; 21 return a + x*(cross(y, ln.a - a))/cross(y, x); 22 } 23 }; 24 25 P circle_center(const P& a, const P& b, const P& c) 26 { 27 const P m = (a+b)/2.0; 28 const P n = (b+c)/2.0; 29 const P x = m + (b-a)*P(0,1); 30 const P y = n + (c-b)*P(0,1); 31 return line(m, x).intersection(line(n, y)); 32 } 33 34 inline bool arc_intersects(const P& a, const P& b, const P& c, const P& p) 35 { 36 return cross(b - a, c - a) * cross(b - a, p - a) > 0.0; 37 } 38 39 int main() 40 { 41 P a, b, c; 42 cin >> a.real() >> a.imag() >> b.real() >> b.imag() >> c.real() >> c.imag(); 43 44 const P o = circle_center(a, b, c); 45 const double R = abs(a - o); 46 const P left = o + P(-R, 0); 47 const P right = o + P(R, 0); 48 const P bottom = o + P(0, -R); 49 const P top = o + P(0, R); 50 51 const int x0 = floor(arc_intersects(a, b, c, left) ? left.real() : min(a.real(), b.real())); 52 const int x1 = ceil(arc_intersects(a, b, c, right) ? right.real() : max(a.real(), b.real())); 53 const int y0 = floor(arc_intersects(a, b, c, bottom) ? bottom.imag() : min(a.imag(), b.imag())); 54 const int y1 = ceil(arc_intersects(a, b, c, top) ? top.imag() : max(a.imag(), b.imag())); 55 cout << (x1 - x0)*(y1 - y0) << endl; 56 return 0; 57 }