POJ 1279 - Art Gallery
http://poj.org/problem?id=1279
概要
N 頂点の多角形(凸とは限らない)が与えられ,辺上のどの位置からも見える多角形の内側の領域の面積を答える.
制約
- 5 <= N <= 1500
- 座標の値は 16bit の符号付き整数に収まる
- 10^-2 の精度で出力する
解法
各辺に沿って多角形を切断し,残った多角形の面積を出力する.
poj/1279.cc1 #include <cstdio> 2 #include <vector> 3 #include <complex> 4 #include <cmath> 5 using namespace std; 6 typedef complex<double> P; 7 static const double EPS = 1e-6; 8 static const double PI = acos(-1.0); 9 10 inline double cross(const P& a, const P& b) 11 { 12 return a.real()*b.imag() - b.real()*a.imag(); 13 } 14 15 struct line 16 { 17 P a, b; 18 line() {} 19 line(const P& x, const P& y) : a(x), b(y) {} 20 }; 21 22 struct segment 23 { 24 P a, b; 25 segment(const P& x, const P& y) : a(x), b(y) {} 26 inline bool intersects(const line& ln) const 27 { 28 return cross(ln.b - ln.a, a - ln.a) * cross(ln.b - ln.a, b - ln.a) < EPS; 29 } 30 31 inline P intersection(const line& ln) const 32 { 33 const P x = b - a; 34 const P y = ln.b - ln.a; 35 return a + x*(cross(y, ln.a - a))/cross(y, x); 36 } 37 38 inline bool parallel(const line& ln) const 39 { 40 const double a = abs(arg(b - a) - arg(ln.b - ln.a)); 41 return a < EPS || abs(PI - a) < EPS; 42 } 43 }; 44 45 struct polygon 46 { 47 vector<P> ps; 48 polygon() {} 49 polygon(const vector<P>& v) : ps(v) {} 50 51 inline int size() const { return ps.size(); } 52 inline void push_back(const P& p) { ps.push_back(p); } 53 inline P& operator[](int i) { return ps[i]; } 54 inline const P& operator[](int i) const { return ps[i]; } 55 56 double area() const 57 { 58 // positive if polygon is clockwise 59 double a = 0.0; 60 const int N = ps.size(); 61 for (int i = 0; i < N; i++) { 62 a += cross(ps[(i+1)%N], ps[i]); 63 } 64 return a/2.0; 65 } 66 67 polygon cut(const line& ln) const 68 { 69 // cut out the left-side of the line 70 const int N = ps.size(); 71 polygon ret; 72 for (int i = 0; i < N; i++) { 73 const segment seg(ps[i], ps[(i+1)%N]); 74 if (cross(ln.b - ln.a, ps[i] - ln.a) < EPS) { 75 // ps[i] is right-side of the line 76 ret.push_back(ps[i]); 77 if (!seg.parallel(ln) && seg.intersects(ln)) { 78 const P p = seg.intersection(ln); 79 if (abs(p - ps[i]) > EPS) { 80 ret.push_back(p); 81 } 82 } 83 } else if (!seg.parallel(ln) && seg.intersects(ln)) { 84 ret.push_back(seg.intersection(ln)); 85 } 86 } 87 return ret; 88 } 89 }; 90 91 int main() 92 { 93 int T; 94 scanf("%d", &T); 95 while (T-- > 0) { 96 int N; 97 scanf("%d", &N); 98 polygon poly; 99 for (int i = 0; i < N; i++) { 100 int x, y; 101 scanf("%d %d", &x, &y); 102 poly.push_back(P(x, y)); 103 } 104 105 polygon ans = poly; 106 for (int i = 0; i < N; i++) { 107 ans = ans.cut(line(poly[i], poly[(i+1)%N])); 108 } 109 printf("%.2f\n", ans.area()); 110 } 111 return 0; 112 }