搞了好久都过不了,看了下题解是用PSLG来做的。POJ 2164 && LA 3218 Find the Border (Geometry, PSLG 平面直线图) - LyonLys - 博客园 这篇里面写过一下,就是把点都提取出来,然后模拟沿着边界移动,找到多边形并计算面积。
而我的做法是直接模拟多边形切割,各种超时爆内存。先留着,看以后能不能用这个来过。
没过的代码:
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <cmath> 6 #include <vector> 7 #include <queue> 8 9 using namespace std; 10 11 const double EPS = 1e-4; 12 inline int sgn(double x) { return (x > EPS) - (x < -EPS);} 13 struct Point { 14 double x, y; 15 Point() {} 16 Point(double x, double y) : x(x), y(y) {} 17 Point operator + (Point a) { return Point(x + a.x, y + a.y);} 18 Point operator - (Point a) { return Point(x - a.x, y - a.y);} 19 Point operator * (double p) { return Point(x * p, y * p);} 20 Point operator / (double p) { return Point(x / p, y / p);} 21 bool operator < (Point a) const { return sgn(x - a.x) < 0 || sgn(x - a.x) == 0 && y < a.y;} 22 bool operator == (Point a) const { return sgn(x - a.x) == 0 && sgn(y - a.y) == 0;} 23 } ; 24 25 inline double cross(Point a, Point b) { return a.x * b.y - a.y * b.x;} 26 inline double dot(Point a, Point b) { return a.x * b.x + a.y * b.y;} 27 inline double veclen(Point x) { return sqrt(dot(x, x));} 28 inline Point normal(Point x) { return Point(-x.y, x.x) / veclen(x);} 29 inline Point vecunit(Point x) { return x / veclen(x);} 30 31 struct Line { 32 Point s, t; 33 Line() {} 34 Line(Point s, Point t) : s(s), t(t) {} 35 Point vec() { return t - s;} 36 Point point(double x) { return s + vec() * x;} 37 } ; 38 inline Point llint(Line a, Line b) { return a.point(cross(b.vec(), a.s - b.s) / cross(a.vec(), b.vec()));} 39 inline bool onseg(Point x, Point s, Point t) { return sgn(cross(s - x, t - x)) == 0 && sgn(dot(s - x, t - x)) < 0;} 40 inline bool onseg(Point x, Line a) { return onseg(x, a.s, a.t);} 41 42 struct Circle { 43 Point c; 44 double r; 45 Circle() {} 46 Circle(Point c, double r) : c(c), r(r) {} 47 bool in(Point x) { return sgn(veclen(x - c) - r) <= 0;} 48 Point point(double x) { return Point(c.x + cos(x) * r, c.y + sin(x) * r);} 49 } ; 50 const double R = 10.0; 51 Circle cake = Circle(Point(0.0, 0.0), R); 52 const double PI = acos(-1.0); 53 template<class T> T sqr(T x) { return x * x;} 54 inline double angle(Point x) { return atan2(x.y, x.x);} 55 56 int clint(Line s, Point *sol) { 57 Point nor = normal(s.vec()), ip = llint(s, Line(cake.c, cake.c + nor)); 58 double dis = veclen(cake.c - ip); 59 if (sgn(dis - cake.r) >= 0) return 0; 60 Point dxy = vecunit(s.vec()) * sqrt(sqr(cake.r) - sqr(dis)); 61 int ret = 0; 62 sol[ret] = ip + dxy; 63 if (onseg(sol[ret], s)) ret++; 64 sol[ret] = ip - dxy; 65 if (onseg(sol[ret], s)) ret++; 66 return ret; 67 } 68 69 double getsec(Point a, Point b) { 70 double a1 = angle(a - cake.c); 71 double a2 = angle(b - cake.c); 72 double da = fabs(a1 - a2); 73 if (da > PI) da = PI * 2.0 - da; 74 return sqr(cake.r) * da * sgn(cross(a - cake.c, b - cake.c)) / 2.0; 75 } 76 77 inline double gettri(Point a, Point b) { return cross(a - cake.c, b - cake.c) / 2.0;} 78 //typedef vector<Point> VP; 79 const int N = 111; 80 struct VP { 81 Point vex[N]; 82 int n; 83 void clear() { n = 0;} 84 void push_back(Point x) { vex[n++] = x;} 85 void pop_back() { n--;} 86 int size() { return n;} 87 } ; 88 89 double cpint(VP pt) { 90 double ret = 0.0; 91 int n = pt.size(); 92 Point tmp[2]; 93 pt.vex[n] = pt.vex[0]; 94 for (int i = 0; i < n; i++) { 95 int ic = clint(Line(pt.vex[i], pt.vex[i + 1]), tmp); 96 if (ic == 0) { 97 if (!cake.in(pt.vex[i]) || !cake.in(pt.vex[i + 1])) ret += getsec(pt.vex[i], pt.vex[i + 1]); 98 else ret += gettri(pt.vex[i], pt.vex[i + 1]); 99 } else if (ic == 1) { 100 if (cake.in(pt.vex[i])) ret += gettri(pt.vex[i], tmp[0]), ret += getsec(tmp[0], pt.vex[i + 1]); 101 else ret += getsec(pt.vex[i], tmp[0]), ret += gettri(tmp[0], pt.vex[i + 1]); 102 } else { 103 if (pt.vex[i] < pt.vex[i + 1] ^ tmp[0] < tmp[1]) swap(tmp[0], tmp[1]); 104 ret += getsec(pt.vex[i], tmp[0]); 105 ret += gettri(tmp[0], tmp[1]); 106 ret += getsec(tmp[1], pt.vex[i + 1]); 107 } 108 // cout << "~~ic " << ic << ' ' << ret << endl; 109 } 110 return fabs(ret); 111 } 112 113 bool fixpoly(VP &poly) { 114 double sum = 0.0; 115 int n = poly.size(); 116 poly.vex[n] = poly.vex[0]; 117 for (int i = 0; i < n; i++) sum += cross(poly.vex[i], poly.vex[i + 1]); 118 if (sgn(sum) == 0) return false; 119 if (sgn(sum) < 0) reverse(poly.vex, poly.vex + n); 120 return true; 121 } 122 123 void cutpoly(VP &poly, Line l, VP &ret) { 124 ret.clear(); 125 int n = poly.size(); 126 // cout << n << endl; 127 poly.vex[n] = poly.vex[0]; 128 for (int i = 0; i < n; i++) { 129 if (sgn(cross(l.vec(), poly.vex[i] - l.s)) >= 0) ret.push_back(poly.vex[i]); 130 if (sgn(cross(l.vec(), poly.vex[i] - poly.vex[i + 1]))) { 131 Point ip = llint(l, Line(poly.vex[i], poly.vex[i + 1])); 132 // cout << "ip " << ip.x << ' ' << ip.y << endl; 133 if (onseg(ip, poly.vex[i], poly.vex[i + 1]) || poly.vex[i] == ip) ret.push_back(ip); 134 } 135 } 136 // cout << "cp sz " << ret.size() << endl; 137 } 138 139 const int M = 22222; 140 int q[1111111], qh, qt, nu; 141 VP rec[M]; 142 queue<int> recycle; 143 144 int getID() { 145 int ret; 146 if (nu >= M) { 147 if (recycle.empty()) { puts("shit!"); while (1) ;} 148 ret = recycle.front(); 149 recycle.pop(); 150 } else ret = nu++; 151 return ret; 152 } 153 154 void retID(int x) { recycle.push(x);} 155 156 int main() { 157 // freopen("in", "r", stdin); 158 // freopen("out", "w", stdout); 159 int T, n, tmp; 160 double x, y; 161 cin >> T; 162 while (T-- && cin >> n) { 163 while (!recycle.empty()) recycle.pop(); 164 qh = qt = nu = 0; 165 tmp = getID(); 166 rec[tmp].clear(); 167 rec[tmp].push_back(Point(-R * 2.0, -R * 2.0)); 168 rec[tmp].push_back(Point(R * 2.0, -R * 2.0)); 169 rec[tmp].push_back(Point(R * 2.0, R * 2.0)); 170 rec[tmp].push_back(Point(-R * 2.0, R * 2.0)); 171 fixpoly(rec[tmp]); 172 q[qt++] = tmp; 173 for (int i = 0; i < n; i++) { 174 cin >> x >> y; 175 int sz = qt - qh; 176 Line t = Line(cake.point(x), cake.point(y)); 177 // cout << cake.point(x).x << '=' << cake.point(x).y << endl; 178 // cout << cake.point(y).x << '~' << cake.point(y).y << endl; 179 for (int j = 0; j < sz; j++) { 180 tmp = getID(); 181 // cout << "qh ?? " << qh << ' ' << q[qh] << ' ' << rec[q[qh]].size() << endl; 182 cutpoly(rec[q[qh]], t, rec[tmp]); 183 if (fixpoly(rec[tmp])) { 184 // cout << j << "~~1 " << rec[tmp].size() << endl; 185 // for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl; 186 q[qt++] = tmp; 187 } 188 swap(t.s, t.t); 189 tmp = getID(); 190 cutpoly(rec[q[qh]], t, rec[tmp]); 191 if (fixpoly(rec[tmp])) { 192 // cout << j << "~~2 " << rec[tmp].size() << endl; 193 // for (int k = 0; k < rec[tmp].size(); k++) cout << rec[tmp].vex[k].x << ' ' << rec[tmp].vex[k].y << endl; 194 q[qt++] = tmp; 195 } 196 retID(q[qh++]); 197 } 198 // cout << "sz~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ " << qt - qh << endl; 199 } 200 double mx = 0.0; 201 while (qh < qt) { 202 mx = max(mx, cpint(rec[q[qh++]])); 203 // cout << ".. " << mx << endl; 204 } 205 printf("%.2f\n", mx); 206 } 207 return 0; 208 } 209 210 /* 211 6 212 2 213 -3.140000 0.000000 214 -1.000000 1.000000 215 2 216 -3.141592 0.000000 217 -1.570796 1.570796 218 3 219 -3.000000 3.000000 220 -2.000000 2.000000 221 -1.000000 1.000000 222 4 223 -3.140000 0.000000 224 -1.000000 1.000000 225 -3.140000 -1.000000 226 1.000000 0.000000 227 6 228 -3.140000 0.000000 229 -1.000000 1.000000 230 -3.140000 -1.000000 231 1.000000 0.000000 232 -3.140000 -1.000000 233 1.000000 0.000000 234 6 235 -3.141592 0.000000 236 -1.570796 1.570796 237 -3.141592 -1.570796 238 0.000000 1.570796 239 -3.141592 1.570796 240 0.000000 -1.570796 241 */