给出平面上的N个点
对于平面上的一点p,要求任何一条通过p且不经过上面N个点的直线,其两侧的点数都不少于⌊N/3⌋
问符合上面要求的点形成的区域的面积是多少
假如一个点一侧有少于n/3个点,这个点这一侧所有点都不可能
因此对于所有右侧恰好有n/3 - 1个点的直线做半平面交就是答案
1 #include <cstdio> 2 #include <iostream> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 #define V P 7 const double eps = 1e-6; 8 inline int dcmp (double x) { 9 return x < -eps ? -1 : x > eps; 10 } 11 struct P { 12 double x, y; 13 void scan() { 14 scanf("%lf%lf", &x, &y); 15 } 16 P(double _x = 0, double _y = 0) : x(_x), y(_y) { } 17 V operator + (V a) const { 18 return V(x + a.x, y + a.y); 19 } 20 V operator - (V a) const { 21 return V(x - a.x, y - a.y); 22 } 23 V operator * (double p) const { 24 return V(p * x, p * y); 25 } 26 V operator / (double p) const { 27 return V(x / p, y / p); 28 } 29 bool operator < (P a) const { 30 return x < a.x || (dcmp(x - a.x) == 0 && y < a.y); 31 } 32 bool operator == (P a) const { 33 return dcmp(x - a.x) == 0 && dcmp(y - a.y) == 0; 34 } 35 }; 36 37 inline double dot(V a, V b) { 38 return a.x * b.x + a.y * b.y; 39 } 40 inline double len(V a) { 41 return sqrt(dot(a, a)); 42 } 43 inline double dis(P a, P b) { 44 return len(b - a); 45 } 46 inline double ang(V a, V b) { 47 return acos(dot(a, b) / len(a) / len(b)); 48 } 49 inline double cross(V a, V b) { 50 return a.x * b.y - a.y * b.x; 51 } 52 inline double area(P a, P b, P c) { 53 return cross(b - a, c - a); 54 } 55 V rot(V a, double p) { 56 return V(a.x * cos(p) - a.y * sin(p), a.x * sin(p) + a.y * cos(p)); 57 } 58 V normal(V a) { 59 double L = len(a); 60 return V(-a.y / L, a.x / L); 61 } 62 P inter(P p, V v, P q, V w) { 63 V u = p - q; 64 double t = cross(w, u) / cross(v, w); 65 return p + v * t; 66 } 67 double dis(P p, P a, P b) { 68 V v1 = b - a, v2 = p - a; 69 return fabs(cross(v1, v2)) / len(v1); 70 } 71 double dis2(P p, P a, P b) { 72 if (a == b) return len(p - a); 73 V v1 = b - a, v2 = p - a, v3 = p - b; 74 if (dcmp(dot(v1, v2)) < 0) return len(v2); 75 else if (dcmp(dot(v1, v3)) > 0) return len(v3); 76 else return fabs(cross(v1, v2)) / len(v1); 77 } 78 P proj(P p, P a, P b) { 79 V v = b - a; 80 return a + v * (dot(v, p - a) / dot(v, v)); 81 } 82 bool isInter(P a1, P a2, P b1, P b2) { 83 double c1 = cross(a2 - a1, b1 - a1), c2 = cross(a2 - a1, b2 - a1), 84 c3 = cross(b2 - b1, a1 - b1), c4 = cross(b2 - b1, a2 - b1); 85 return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0; 86 } 87 bool onSeg(P p, P a1, P a2) { 88 return dcmp(cross(a1 - p, a2 - p)) == 0 && dcmp(dot(a1 - p, a2 - p)) < 0; 89 } 90 91 double area(P* p, int n) { 92 double s = 0; 93 p[n] = p[0]; 94 for (int i = 1; i < n; i ++) 95 s += cross(p[i] - p[0], p[i + 1] - p[0]); 96 return s / 2; 97 } 98 int graham(P* p, int n, P* ch) { 99 sort(p, p + n); 100 int m = 0; 101 for (int i = 0; i < n; i ++) { 102 while (m > 1 && cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m --; 103 ch[m ++] = p[i]; 104 } 105 int k = m; 106 for (int i = n - 2; i >= 0; i --) { 107 while (m > k && cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m --; 108 ch[m ++] = p[i]; 109 } 110 if (n > 1) m --; 111 return m; 112 } 113 struct L { 114 P p; 115 V v; 116 double ang; 117 L() {} 118 L(P _p, V _v) : p(_p), v(_v) { ang = atan2(v.y, v.y); } 119 bool operator < (const L& L) const { 120 return ang < L.ang; 121 } 122 }; 123 inline int get(P a) { 124 if( a.x > 0 && a.y >= 0) return 1; 125 if( a.x <= 0 && a.y > 0) return 2; 126 if( a.x < 0 && a.y <= 0) return 3; 127 if( a.x >= 0 && a.y < 0) return 4; 128 return 0; 129 } 130 inline bool cmp2 (L a, L b) { 131 return get(a.v) < get(b.v) || (get(a.v) == get(b.v) && dcmp( cross(a.v, b.v) ) >0); 132 } 133 bool onLeft(L l, P p) { 134 return cross(l.v, p - l.p) > 0; 135 } 136 P inter(L a, L b) { 137 return inter(a.p, a.v, b.p, b.v); 138 } 139 int half(L* l, int n, P* po) { 140 sort(l, l + n, cmp2); 141 int h, t; 142 P *p = new P[n]; 143 L *q = new L[n]; 144 q[h = t = 0] = l[0]; 145 for (int i = 1; i < n; i ++) { 146 while (h < t && !onLeft(l[i], p[t - 1])) t --; 147 while (h < t && !onLeft(l[i], p[h])) h ++; 148 q[++ t] = l[i]; 149 if (dcmp(cross(q[t].v, q[t - 1].v)) == 0) { 150 t --; 151 if (onLeft(q[t], l[i].p)) q[t] = l[i]; 152 } 153 if (h < t) p[t - 1] = inter(q[t - 1], q[t]); 154 } 155 while (h < t && !onLeft(q[h], p[t - 1])) t --; 156 if (t - h <= 1) return 0; 157 p[t] = inter(q[t], q[h]); 158 int m = 0; 159 for (int i = h; i <= t; i ++) po[m ++] = p[i]; 160 return m; 161 } 162 inline bool cmp (V a, V b) { 163 return get(a) < get(b) || (get(a) == get(b) && dcmp( cross(a, b) ) >0); 164 } 165 const int N = 101000; 166 int n; 167 P a[N], b[N], res[N]; 168 L l[N]; 169 int main() { 170 freopen("a.in", "r", stdin); 171 int T; 172 scanf("%d", &T); 173 for (int cas = 1; cas <= T; cas ++) { 174 scanf("%d", &n); 175 for (int i = 0; i < n; i ++) 176 a[i].scan(); 177 int bound = n / 3 - 1, l_c = 0; 178 for (int i = 0; i < n; i ++) { 179 int cnt = 0; 180 for (int j = 0; j < n; j ++) 181 if (j != i) 182 b[cnt ++] = a[j] - a[i]; 183 sort(b, b + cnt, cmp); 184 int t = 0, sum = 0; 185 for (int j = 0; j < cnt; j ++) { 186 //if (j == 1) printf("fuck %d %d ", dcmp(cross(b[j], b[(t + 1) % cnt])), dcmp(dot(b[j], b[(t + 1) % cnt]))); 187 while ((dcmp(cross(b[j], b[(t + 1) % cnt])) == 1) || 188 (dcmp(cross(b[j], b[(t + 1) % cnt])) == 0 && 189 dcmp(dot(b[j], b[(t + 1) % cnt])) == -1)) t = (t + 1) % cnt, sum ++; 190 if (cnt - (sum + 1) == bound) l[l_c ++] = L(a[i], b[j]); 191 //if (i == 0) printf("%d ", sum); 192 if (t == j) t ++; 193 else { 194 while (dcmp(cross(b[j], b[(j + 1) % cnt])) == 0) j ++, sum --; 195 sum --; 196 } 197 } 198 } 199 //printf("%d ", l_c); 200 //for (int i = 0; i < l_c; i ++) 201 // printf("%lf %lf %lf %lf ", l[i].p.x, l[i].p.y, l[i].v.x, l[i].v.y); 202 int ans = half(l, l_c, res); 203 //printf("%d ", ans); 204 //for (int i = 0; i < ans; i ++) 205 // printf("%lf %lf ", res[i].x, res[i].y); 206 printf("Case #%d: %.6lf ", cas, area(res, ans)); 207 } 208 return 0; 209 }