Cod sursa(job #1053885)

Utilizator fmins123FMI No Stress fmins123 Data 12 decembrie 2013 23:52:11
Problema Triangulare Scor Ascuns
Compilator cpp Status done
Runda Marime 3.71 kb
#include <fstream>
#include <vector>
using namespace std;

ifstream fin("triangulare.in");
ofstream fout("triangulare.out");

const double EPS = 1e-10;

inline double abs(double X) {
   if (X + EPS < 0)
      return -X;
   if (X - EPS > 0)
      return X;
   return 0;
}

inline bool egal(double A,double B) {
   return abs(A - B) < EPS;
}

struct Punct {
   double x, y;
   Punct() { x = y = 0; }
   Punct(const Punct &that) { *this = that; }
   Punct(const double &a, const double &b) { x = a; y = b; }

   bool operator==(const Punct &that) const {
      return egal(x, that.x) && egal(y, that.y);
   }
};

struct Segment {
   Punct x, y;
   double A, B, C;
   Segment() { A = B = C = 0; }
   Segment(const Segment &that) { *this = that; }
   Segment(const Punct &a, const Punct &b) { 
      x = a; y = b; 

      A = b.y - a.y;  
      B = a.x - b.x; 
      C = A * a.x + B * a.y; 
   }
};

vector <pair <int, int> > ret;
vector <Punct> pct;
int T, N;

inline int sgn(double X) {
   if (X + EPS < 0)
      return -1;
   if (X - EPS > 0)
      return 1;
   return 0;
}

inline int parte(Segment S, Punct P) {
   return sgn(S.A * P.x + S.B * P.y - S.C);
}

inline bool intersectDreapta(Segment D, Segment S) {
   return parte(D, S.x) * parte(D, S.y) <= 0;
}

inline bool apartineDreapta(Segment S, Punct P) {
   return egal(S.A * P.x + S.B * P.y - S.C, 0);
}

inline bool apartine(Segment S, Punct P) {
   return apartineDreapta(S, P) && egal(abs(S.x.x - P.x) + abs(S.y.x - P.x), abs(S.x.x - S.y.x)) && egal(abs(S.x.y - P.y) + abs(S.y.y - P.y), abs(S.x.y - S.y.y));
}

inline bool intersect(Segment S1, Segment S2) {
   if (apartineDreapta(S1, S2.x) && apartineDreapta(S1, S2.y))
      return apartine(S1, S2.x) || apartine(S1, S2.y) || apartine(S2, S1.x) || apartine(S2, S1.y);
   return intersectDreapta(S1, S2) && intersectDreapta(S2, S1);
}

vector <pair <int, int> > solve(int N, vector<Punct> pct) {
   vector <pair <int, int> > ret;
   vector <Segment> seg;
   for (int i = 0; i < N; ++ i)
      seg.push_back(Segment(pct[i], pct[(i + 1) % N]));

   for (int it = 0; it < N - 3; ++ it) {
      int notFound = 1;
      
      for (int i = 0; i < N && notFound; ++ i)
         for (int j = i + 1; j < N && notFound; ++ j) {
            if (i == (j + 1) % N || j == (i + 1) % N)
               continue ;

            int isOk = 1;
            Segment check = Segment(pct[i], pct[j]);
            for (int k = 0; k < (int)seg.size(); ++k) {
               if ((seg[k].x == check.x && seg[k].y == check.y) || (seg[k].x == check.y && seg[k].y == check.x)) {
                  isOk = 0;
                  break ;
               }

               if (seg[k].x == check.x || seg[k].x == check.y || seg[k].y == check.x || seg[k].y == check.y)
                  continue ;

               if (intersect(check, seg[k])) {
                  isOk = 0;
                  break ;
               }
            }

            if (isOk) {
               int inPoly = false;
               Segment test = Segment(Punct(666013.555, -123456.789), Punct((pct[i].x + pct[j].x) / 2.0, (pct[i].y + pct[j].y) / 2.0));
               
               for (int k = 0; k < N; ++ k)
                  if (intersect(test, seg[k]))
                     inPoly ^= 1;

               if (!inPoly)
                  continue ;

               ret.push_back(make_pair(i, j));
               seg.push_back(check);
               notFound = 0;
            }
         }
      }

   return ret;
}

int main () {
  fin >> T;
  for (int t = 1; t <= T; ++  t) {
   fin >> N;
   pct.clear();
   for (int i = 0; i < N; ++ i) {
      int x, y; fin >> x >> y;
      pct.push_back(Punct(x, y));
   }

   ret = solve(N, pct);
   
   for (int i = 0; i < N - 3; ++ i)   
      fout << ret[i].first << " " << ret[i].second << "\n";
  }
}