1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
| #include <algorithm> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <vector>
using namespace std;
const int MAX = 50100; const double oo = 1e10; const double eps = 1e-8;
struct Point { double x, y; double angle, dis; Point() {} Point(double x, double y) : x(x), y(y) {} };
struct Line { Point p1, p2; Line() {} Line(Point p1, Point p2) : p1(p1), p2(p2) {} }; typedef vector<Point> Polygon; typedef vector<Point> Points;
bool ZERO(double x) { return fabs(x) < eps; } bool ZERO(Point p) { return ZERO(p.x) && ZERO(p.y); } bool EQ(double x, double y) { return fabs(x - y) < eps; } bool NEQ(double x, double y) { return fabs(x - y) >= eps; } bool LT(double x, double y) { return NEQ(x, y) && x < y; } bool GT(double x, double y) { return NEQ(x, y) && x > y; } bool LEQ(double x, double y) { return EQ(x, y) || x < y; } bool GEQ(double x, double y) { return EQ(x, y) || x > y; } double sqr(double x) { return x * x; }
bool operator==(const Point& p1, const Point& p2) { return EQ(p1.x, p2.x) && EQ(p1.y, p2.y); }
bool operator!=(const Point& p1, const Point& p2) { return NEQ(p1.x, p2.x) || NEQ(p1.y, p2.y); }
bool operator<(const Point& p1, const Point& p2) { if (NEQ(p1.x, p2.x)) { return p1.x < p2.x; } else { return p1.y < p2.y; } }
Point operator+(const Point& p1, const Point& p2) { return Point(p1.x + p2.x, p1.y + p2.y); }
Point operator-(const Point& p1, const Point& p2) { return Point(p1.x - p2.x, p1.y - p2.y); }
double operator*(const Point& p1, const Point& p2) { return p1.x * p2.y - p1.y * p2.x; }
double operator&(const Point& p1, const Point& p2) { return p1.x * p2.x + p1.y * p2.y; }
double Norm(const Point& p) { return sqrt(sqr(p.x) + sqr(p.y)); }
bool comp(const Point& left, const Point& right) { if (EQ(left.angle, right.angle)) { return left.dis < right.dis; } else { return left.angle < right.angle; } }
void Scan(Points& points, Polygon& result) { int i, k, n; Point p; n = points.size(); result.clear(); if (n < 3) { result = points; return; } k = 0; for (i = 1; i < n; i++) { if (EQ(points[i].y, points[k].y)) { if (points[i].x <= points[k].x) { k = i; } } else if (points[i].y < points[k].y) { k = i; } } swap(points[0], points[k]); for (i = 1; i < n; i++) { points[i].angle = atan2(points[i].y - points[0].y, points[i].x - points[0].x); points[i].dis = Norm(points[i] - points[0]); } sort(points.begin() + 1, points.end(), comp); result.push_back(points[0]); for (i = 1; i < n; i++) { if ((i + 1 < n) && EQ(points[i].angle, points[i + 1].angle)) { continue; } if (result.size() >= 3) { p = result[result.size() - 2]; while (GEQ((points[i] - p) * (result.back() - p), 0)) { result.pop_back(); p = result[result.size() - 2]; } } result.push_back(points[i]); } }
Point center(const Polygon& poly) { Point p, p0, p1, p2, p3; double m, m0; p1 = poly[0]; p2 = poly[1]; p.x = p.y = m = 0; for (int i = 2; i < (int)poly.size(); i++) { p3 = poly[i]; p0.x = (p1.x + p2.x + p3.x) / 3.0; p0.y = (p1.y + p2.y + p3.y) / 3.0; m0 = p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.y * p2.x - p2.y * p3.x - p3.y * p1.x; if (ZERO(m + m0)) { m0 += eps; } p.x = (m * p.x + m0 * p0.x) / (m + m0); p.y = (m * p.y + m0 * p0.y) / (m + m0); m += m0; p2 = p3; } return p; }
bool isconter(const Points pts) { double res = 0.0; int n = pts.size(); for (int i = 0; i < n; i++) { res += (pts[i] * pts[(i + 1) % n]); } return res > 0; }
bool check(const Point& p, const Line& l) { return LT((l.p1 - p) & (l.p2 - l.p1), 0) & < ((l.p2 - p) & (l.p1 - l.p2), 0); }
Points pts, poly; int main() { int t; int n, ret; Point p; scanf("%d", &t); while (t--) { scanf("%d", &n); ret = 0; pts.clear(); for (int i = 0; i < n; i++) { scanf("%lf%lf", &p.x, &p.y); pts.push_back(p); } if (!isconter(pts)) { reverse(pts.begin(), pts.end()); } p = center(pts); Scan(pts, poly); n = poly.size(); poly.push_back(poly[0]); for (int i = 0; i < n; i++) { if (check(p, Line(poly[i], poly[i + 1]))) { ret++; } } printf("%d\n", ret); } return 0; }
|