Prérequis : PEU Étant donné 'n' segments de ligne, chacun d'eux est horizontal ou vertical, trouvez le nombre maximum de triangles (y compris les triangles de surface nulle) qui peuvent être formés en joignant les points d'intersection des segments de ligne. Deux segments de ligne horizontaux ne se chevauchent pas, pas plus que deux segments de ligne verticaux. Une ligne est représentée à l'aide de deux points (quatre entiers, les deux premiers étant respectivement les coordonnées x et y du premier point et les deux autres étant les coordonnées x et y du deuxième point) Exemples :
| ---|-------|-- | | ----- | --|--|- | | | | 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.
L'idée est basée sur Algorithme de ligne de balayage . Construire une solution par étapes :
- Stockez les deux points de tous les segments de ligne avec l'événement correspondant (décrit ci-dessous) dans un vecteur et triez tous les points par ordre non décroissant de leurs coordonnées x.
- Imaginons maintenant une ligne verticale que nous balayons sur tous ces points et décrivons 3 événements en fonction du point où nous nous trouvons actuellement :
- un ligne verticale
- Nous appelons la région 'actif' ou les lignes horizontales 'actif' qui ont eu le premier événement mais pas le deuxième. Nous aurons un BIT (arbre indexé binaire) pour stocker les coordonnées « y » de toutes les lignes actives.
- Une fois qu'une ligne devient inactive, nous supprimons son « y » du BIT.
- Lorsqu'un événement du troisième type se produit, c'est-à-dire lorsque nous sommes sur une ligne verticale, nous interrogeons l'arbre dans la plage de ses coordonnées « y » et ajoutons le résultat au nombre de points d'intersection jusqu'à présent.
- Finalement nous aurons le nombre de points d'intersections dire m alors le nombre de triangles (y compris l'aire zéro) sera mC3 .
dans - point le plus à gauche d'un segment de ligne horizontaledehors - point le plus à droite d'un segment de ligne horizontaleNote: Nous devons trier soigneusement les points, regardez le cmp() fonction dans la mise en œuvre à des fins de clarification.
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; } Sortir:
Number of triangles are: 4
Time Complexity: O( n * log(n) + n * log(maximum_y) )
Espace auxiliaire : O(maxy) où maxy = 1000005