logo

Encontrar el número de triángulos entre segmentos de recta horizontal y vertical

Requisitos previos: POCO  Dados 'n' segmentos de línea, cada uno de ellos es horizontal o vertical, encuentre el número máximo de triángulos (incluidos los triángulos con área cero) que se pueden formar uniendo los puntos de intersección de los segmentos de línea. No se superponen dos segmentos de línea horizontal ni dos segmentos de línea vertical. Una línea se representa usando dos puntos (cuatro números enteros, los dos primeros son las coordenadas xey respectivamente para el primer punto y los otros dos son las coordenadas xey para el segundo punto) Ejemplos:

 | ---|-------|-- | | ----- | --|--|- | | | | For the above line segments there are four points of intersection between vertical and horizontal lines every three out of which form a triangle so there can be   4C3   triangles.

La idea se basa en Algoritmo de línea de barrido . Construyendo una solución en pasos:



  1. Almacene ambos puntos de todos los segmentos de línea con el evento correspondiente (descrito a continuación) en un vector y ordene todos los puntos en orden no decreciente de sus coordenadas x.
  2. Imaginemos ahora una línea vertical que recorremos todos estos puntos y describimos 3 eventos según el punto en el que nos encontramos actualmente:
      en- punto más a la izquierda de un segmento de línea horizontalafuera- punto más a la derecha de un segmento de línea horizontal
    • a línea vertical
  3. Llamamos a la región 'activo' o las líneas horizontales 'activo' que han tenido el primer evento pero no el segundo. Tendremos un BIT (árbol indexado binario) para almacenar las coordenadas 'y' de todas las líneas activas.
  4. Una vez que una línea queda inactiva, eliminamos su 'y' del BIT.
  5. Cuando ocurre un evento de tercer tipo, es decir, cuando estamos en una línea vertical, consultamos el árbol en el rango de sus coordenadas 'y' y sumamos el resultado al número de puntos de intersección hasta el momento.
  6. Finalmente tendremos el número de puntos de intersecciones, digamos. metro entonces el número de triángulos (incluyendo el área cero) será metrodo3 .

Nota: Necesitamos ordenar cuidadosamente los puntos. Mire el cmp() función en la implementación para aclarar. 

CPP
// A C++ implementation of the above idea #include   #define maxy 1000005 #define maxn 10005 using namespace std; // structure to store point struct point {  int x y;  point(int a int b)  {  x = a y = b;  } }; // Note: Global arrays are initially zero // array to store BIT and vector to store // the points and their corresponding event number // in the second field of the pair int bit[maxy]; vector<pair<point int> > events; // compare function to sort in order of non-decreasing // x coordinate and if x coordinates are same then // order on the basis of events on the points bool cmp(pair<point int> &a pair<point int> &b) {  if ( a.first.x != b.first.x )  return a.first.x < b.first.x;  //if the x coordinates are same  else  {  // both points are of the same vertical line  if (a.second == 3 && b.second == 3)  {  return true;  }  // if an 'in' event occurs before 'vertical'  // line event for the same x coordinate  else if (a.second == 1 && b.second == 3)  {  return true;  }  // if a 'vertical' line comes before an 'in'  // event for the same x coordinate swap them  else if (a.second == 3 && b.second == 1)  {  return false;  }  // if an 'out' event occurs before a 'vertical'  // line event for the same x coordinate swap.  else if (a.second == 2 && b.second == 3)  {  return false;  }  //in all other situations  return true;  } } // update(y 1) inserts a horizontal line at y coordinate // in an active region while update(y -1) removes it void update(int idx int val) {  while (idx < maxn)  {  bit[idx] += val;  idx += idx & (-idx);  } } // returns the number of lines in active region whose y // coordinate is between 1 and idx int query(int idx) {  int res = 0;  while (idx > 0)  {  res += bit[idx];  idx -= idx & (-idx);  }  return res; } // inserts a line segment void insertLine(point a point b) {  // if it is a horizontal line  if (a.y == b.y)  {  int beg = min(a.x b.x);  int end = max(a.x b.x);  // the second field in the pair is the event number  events.push_back(make_pair(point(beg a.y) 1));  events.push_back(make_pair(point(end a.y) 2));  }  //if it is a vertical line  else  {  int up = max(b.y a.y);  int low = min(b.y a.y);  //the second field of the pair is the event number  events.push_back(make_pair(point(a.x up) 3));  events.push_back(make_pair(point(a.x low) 3));  } } // returns the number of intersection points between all // the lines vertical and horizontal to be run after the // points have been sorted using the cmp() function int findIntersectionPoints() {  int intersection_pts = 0;  for (int i = 0 ; i < events.size() ; i++)  {  //if the current point is on an 'in' event  if (events[i].second == 1)  {  //insert the 'y' coordinate in the active region  update(events[i].first.y 1);  }  // if current point is on an 'out' event  else if (events[i].second == 2)  {  // remove the 'y' coordinate from the active region  update(events[i].first.y -1);  }  // if the current point is on a 'vertical' line  else  {  // find the range to be queried  int low = events[i++].first.y;  int up = events[i].first.y;  intersection_pts += query(up) - query(low);  }  }  return intersection_pts; } // returns (intersection_pts)C3 int findNumberOfTriangles() {  int pts = findIntersectionPoints();  if ( pts >= 3 )  return ( pts * (pts - 1) * (pts - 2) ) / 6;  else  return 0; } // driver code int main() {  insertLine(point(2 1) point(2 9));  insertLine(point(1 7) point(6 7));  insertLine(point(5 2) point(5 8));  insertLine(point(3 4) point(6 4));  insertLine(point(4 3) point(4 5));  insertLine(point(7 6) point(9 6));  insertLine(point(8 2) point(8 5));  // sort the points based on x coordinate  // and event they are on  sort(events.begin() events.end() cmp);  cout << "Number of triangles are: " <<  findNumberOfTriangles() << "n";  return 0; } 

Producción:

Number of triangles are: 4
Time Complexity:   O( n * log(n) + n * log(maximum_y) )  

Espacio auxiliar: O(maxy) donde maxy = 1000005