CompProg

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub Zeldacrafter/CompProg

:heavy_check_mark: tests/aoj/polygon_contains_point.test.cpp

Depends on

Code

#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C"

#include "../../code/geometry/polygon.cc"

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);

  int n;
  cin >> n;
  vector<pt> pts(n);
  F0R(i, n) {
      int x, y;
      cin >> x >> y;
      pts[i] = pt(x, y);
  }

  pts.pb(pts[0]);
  reverse(ALL(pts));

  int q;
  cin >> q;
  while(q--) {
      int x, y;
      cin >> x >> y;
      pt p(x, y);

      bool onSegment = false;
      F0R(i, SZ(pts))
        onSegment |= distToLine(p, pts[i], pts[(i + 1) % SZ(pts)], true) < EPS;

      if(onSegment)
        cout << 1 << endl;
      else if(inPolygon(pts, p))
        cout << 2 << endl;
      else 
        cout << 0 << endl;
  }
}
#line 1 "tests/aoj/polygon_contains_point.test.cpp"
#define PROBLEM "http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=CGL_3_C"

#line 1 "code/template.cc"
// this line is here for a reason
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> ii;
typedef vector<int> vi;
typedef vector<ii> vii;
typedef vector<vi> vvi;
typedef vector<vii> vvii;
#define fi first
#define se second
#define eb emplace_back
#define pb push_back
#define mp make_pair
#define mt make_tuple
#define endl '\n'
#define ALL(x) (x).begin(), (x).end()
#define RALL(x) (x).rbegin(), (x).rend()
#define SZ(x) (int)(x).size()
#define FOR(a, b, c) for (auto a = (b); (a) < (c); ++(a))
#define F0R(a, b) FOR (a, 0, (b))
template <typename T>
bool ckmin(T& a, const T& b) { return a > b ? a = b, true : false; }
template <typename T>
bool ckmax(T& a, const T& b) { return a < b ? a = b, true : false; }
#ifndef DEBUG
#define DEBUG 0
#endif
#define dout if (DEBUG) cerr
#define dvar(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "
#line 2 "code/geometry/geometry.cc"
#define xx real()
#define yy imag()
const double EPS = 1e-9;
const double INF = numeric_limits<double>::max();
using pt = complex<double>;
struct Line {
  double a, b, c;
};  // ax + by + c = 0
double dot(pt a, pt b) { return a.xx * b.xx + a.yy * b.yy; }
double cross(pt a, pt b) { return a.xx * b.yy - a.yy * b.xx; }
double dir(pt a, pt b, pt c) { return cross(b - a, c - a); }
bool cw(pt a, pt b, pt c) { return dir(a, b, c) < 0; }
bool ccw(pt a, pt b, pt c) { return dir(a, b, c) > 0; }
bool collinear(pt a, pt b, pt c) { return abs(dir(a, b, c)) < EPS; }
// Angle between a and b with o as origin (ccw).
// Return value in [0, 2PI)
double angle(pt a, pt b) {
  double ang = arg(a) - arg(b);
  return ang < 0 ? ang + 2 * M_PI : ang;
}
double angle(pt a, pt b, pt o) { return angle(b - o, a - o); }
// Theta in radiens
pt rotate(pt a, double theta) { return a * polar(1.0, theta); }
Line ptToLine(pt p1, pt p2) {
  if (abs(real(p1) - real(p2)) < EPS) {
    return {1.0, 0.0, -real(p1)};
  } else {
    double a = -(imag(p1) - imag(p2)) / (real(p1) - real(p2)),
           c = -(a * real(p1)) - imag(p1);
    return {a, 1.0, c};
  }
}
bool areParallel(Line l1, Line l2) {
  return abs(l1.a - l2.a) < EPS && abs(l1.b - l2.b) < EPS;
}
bool areSame(Line l1, Line l2) {
  return areParallel(l1, l2) && abs(l1.c - l2.c) < EPS;
}
pt intersectPt(Line l1, Line l2) {
  // Does not handle if same or parrallel
  if (areParallel(l1, l2)) return pt(-INF, -INF);
  double x =
      (l2.b * l1.c - l1.b * l2.c) / (l2.a * l1.b - l1.a * l2.b);
  double y;
  if (abs(l1.b) < EPS)
    y = -(l1.a * x + l1.c);
  else
    y = -(l2.a * x + l2.c);
  return pt(x, y);
}
double distToLine(pt p, pt a, pt b, bool segment = false) {
  pt ap = p - a, ab = b - a;
  double u = dot(ap, ab) / (abs(ab) * abs(ab));
  if (segment) {
    if (u < 0.0) return abs(p - a);  // a is closest
    if (u > 1.0) return abs(p - b);  // b is closest
  }
  return abs(p - a - ab * u);      // closest is in segment.
}
#line 2 "code/geometry/polygon.cc"
bool inTriangle(pt a, pt b, pt c, pt p) {
  return
    abs(-abs(dir(a, b, c)) + abs(dir(a, b, p))
        + abs(dir(a, p, c)) + abs(dir(p, b, c))) < EPS;
}
// poly must be sorted in clockwise direction.
// returns true if point is on edge of poly.
bool inPolygon(const vector<pt>& poly, pt p) {
  double sum = 0;
  F0R(i, SZ(poly)) {
    double ang = angle(poly[i], poly[(i + 1) % SZ(poly)], p);
    if(ang > M_PI) ang -= 2*M_PI; // we want angle (-PI, PI] not [0, 2PI)
    sum += ang;
  }
  return abs(abs(sum) - 2*M_PI) < EPS;
}
// poly must be sorted in clockwise direction.
// poly[0] = poly[SZ(poly) - 1]
// returns true if point is on edge of poly.
bool inConvexPolygon(const vector<pt>& poly, pt p) {
  int l = 1, r = SZ(poly) - 2;
  while (l < r) {
    int mid = (l + r) / 2;
    if (cw(poly[0], poly[mid], p))
      l = mid + 1;
    else
      r = mid;
  }
  return inTriangle(poly[0], poly[l], poly[l - 1], p);
}
double area(const vector<pt>& p) {
  double res = 0.0;
  F0R (i, SZ(p))
    res += cross(p[i], p[(i + 1) % SZ(p)]);
  return abs(res) / 2;
}
bool isConvex(const vector<pt>& p) {
  if (SZ(p) < 3) return false;
  bool isLeft = ccw(p[0], p[1], p[2]) || collinear(p[0], p[1], p[2]),
      convex = true;
  F0R (i, SZ(p))
    convex &= isLeft == (ccw(p[i], p[(i + 1) % SZ(p)], p[(i + 2) % SZ(p)])
                     || collinear(p[i], p[(i + 1) % SZ(p)], p[(i + 2) % SZ(p)]));
  return convex;
}
#line 4 "tests/aoj/polygon_contains_point.test.cpp"

int main() {
  cin.tie(0);
  ios_base::sync_with_stdio(0);

  int n;
  cin >> n;
  vector<pt> pts(n);
  F0R(i, n) {
      int x, y;
      cin >> x >> y;
      pts[i] = pt(x, y);
  }

  pts.pb(pts[0]);
  reverse(ALL(pts));

  int q;
  cin >> q;
  while(q--) {
      int x, y;
      cin >> x >> y;
      pt p(x, y);

      bool onSegment = false;
      F0R(i, SZ(pts))
        onSegment |= distToLine(p, pts[i], pts[(i + 1) % SZ(pts)], true) < EPS;

      if(onSegment)
        cout << 1 << endl;
      else if(inPolygon(pts, p))
        cout << 2 << endl;
      else 
        cout << 0 << endl;
  }
}
Back to top page