Cod sursa(job #2314669)

Utilizator NOSCOPEPROKENDYMACHEAMACUMVREAU NOSCOPEPROKENDY Data 8 ianuarie 2019 22:17:11
Problema Triangulare Scor 100
Compilator cpp-64 Status done
Runda Arhiva ICPC Marime 3.69 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;

}