Cod sursa(job #1714544)

Utilizator iulianrotaruRotaru Gheorghe-Iulian iulianrotaru Data 8 iunie 2016 17:34:28
Problema Triangulare Scor 100
Compilator cpp Status done
Runda Arhiva ICPC Marime 3.46 kb
#include <bits/stdc++.h>
using namespace std;
ifstream f("triangulare.in");
ofstream g("triangulare.out");
class Point {
  public:
    int x, y;
    Point(const int _x = 0, const int _y = 0):
      x(_x),
      y(_y) {}
    bool operator==(const Point &other) const {
        return (x == other.x && y == other.y);
    }
};
inline int Det(const Point &p1, const Point &p2, const Point &p3) {
    return p1.x * p2.y + p2.x * p3.y + p3.x * p1.y - p1.x * p3.y - p2.x * p1.y - p3.x * p2.y;
}
class Segment {
  public:
    Point e1, e2;

    Segment(const Point _e1, const Point _e2):
      e1(_e1),
      e2(_e2) {
        if (e1.y > e2.y)
            swap(e1, e2);
    }

    static bool OpenIntersection(const Segment &s1, const Segment &s2) {
        if (s1.e1 == s1.e2 || s2.e1 == s2.e2)
            return false;
        if (Det(s1.e1, s1.e2, s2.e1) == 0 && Det(s1.e1, s1.e2, s2.e2) == 0) {
            if (OpenIntervalIntersection(s1.e1.x, s1.e2.x, s2.e1.x, s2.e2.x))
                return true;
            if (OpenIntervalIntersection(s1.e1.y, s1.e2.y, s2.e1.y, s2.e2.y))
                return true;
            return false;
        }
        return (1LL * Det(s1.e1, s1.e2, s2.e1) * Det(s1.e1, s1.e2, s2.e2) < 0 && 1LL * Det(s2.e1, s2.e2, s1.e1) * Det(s2.e1, s2.e2, s1.e2) < 0);
    }

  private:
    static bool OpenIntervalIntersection(int x1, int x2, int y1, int y2) {
        if (x1 > x2)
            swap(x1, x2);
        if (y1 > y2)
            swap(y1, y2);
        if (x1 > y1) {
            swap(x1, y1);
            swap(x2, y2);
        }
        return y1 < x2;
    }
};
class Polygon {
  public:
    vector<Segment> edges;

    Polygon():
      edges(vector<Segment>()) {}

    Polygon(const vector<Point> &points) {
        int sf=points.size();
        for (int i = 0; i < sf; ++i)
            edges.push_back(Segment(points[i], points[(i + 1) %sf]));
    }

    bool IsInside(const Point &p) const {
        int intersect = 0;
        for (const auto &segment: edges)
            if (segment.e1.y < p.y && p.y <= segment.e2.y && Det(segment.e1, segment.e2, p) < 0)
                ++intersect;
        return intersect&1;
    }
};
vector<Point> Points;
Polygon P;
int N;
vector< pair<int, int> > Triangulation;
inline bool CheckSegment(const Segment &edge) {
    for (const auto &e: P.edges)
        if (Segment::OpenIntersection(e, edge))
            return false;
    for (const auto &e: Triangulation)
        if (Segment::OpenIntersection(Segment(Points[e.first], Points[e.second]), edge))
            return false;
    return P.IsInside(Point((edge.e1.x + edge.e2.x)>>1, (edge.e1.y + edge.e2.y)>>1));
}
void Solve() {
    Triangulation = vector< pair<int, int> >();
    for (int i = 0; i < N; ++i)
        for (int j = (i + 2) % N; (j + 1) % N != i; j = (j + 1) % N)
            if (CheckSegment(Segment(Points[i], Points[j])))
                Triangulation.push_back(make_pair(i, j));
    sort(Triangulation.begin(), Triangulation.end());
}
void Read() {
    f>>N;
    Points = vector<Point>(N);
    for (int i = 0; i < N; ++i) {
        f>>Points[i].x>>Points[i].y;
        Points[i].x<<=1;
        Points[i].y<<=1;
    }
    P = Polygon(Points);
}
void Print() {
    for (const auto &segment: Triangulation)
        g<<segment.first<<' '<<segment.second<<'\n';
}
int main() {
    int t;
    f>>t;
    while(t--) {
        Read();
        Solve();
        Print();
    }
    return 0;
}