logo

Het aantal driehoeken tussen horizontale en verticale lijnsegmenten vinden

Vereisten: BEETJE  Gegeven 'n' lijnsegmenten, elk van hen is horizontaal of verticaal, zoek het maximale aantal driehoeken (inclusief driehoeken met een nulgebied) dat kan worden gevormd door de snijpunten van de lijnsegmenten met elkaar te verbinden. Er overlappen geen twee horizontale lijnsegmenten, noch twee verticale lijnsegmenten. Een lijn wordt weergegeven met behulp van twee punten (vier gehele getallen, waarvan de eerste twee respectievelijk de x- en y-coördinaten zijn voor het eerste punt en de andere twee de x- en y-coördinaten voor het tweede punt) Voorbeelden:

 | ---|-------|-- | | ----- | --|--|- | | | | 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.

Het idee is gebaseerd op Sweeplijnalgoritme . In stappen een oplossing bouwen:



  1. Sla beide punten van alle lijnsegmenten met de bijbehorende gebeurtenis (hieronder beschreven) op in een vector en sorteer alle punten in niet-afnemende volgorde van hun x-coördinaten.
  2. Laten we ons nu een verticale lijn voorstellen die we over al deze punten trekken en drie gebeurtenissen beschrijven op basis van het punt waar we ons momenteel bevinden:
      in- meest linkse punt van een horizontaal lijnsegmentuit- meest rechtse punt van een horizontaal lijnsegment
    • A verticale lijn
  3. Wij bellen de regio 'actief' of de horizontale lijnen 'actief' die het eerste evenement hebben gehad, maar niet het tweede. We zullen een BIT (Binary Indexed Tree) hebben om de 'y'-coördinaten van alle actieve lijnen op te slaan.
  4. Zodra een regel inactief wordt, verwijderen we de 'y' uit de BIT.
  5. Wanneer zich een gebeurtenis van het derde type voordoet, dat wil zeggen wanneer we ons op een verticale lijn bevinden, ondervragen we de boom binnen het bereik van zijn 'y'-coördinaten en voegen we het resultaat toe aan het aantal snijpunten tot nu toe.
  6. Tenslotte zullen we het aantal snijpunten zeggen M dan zal het aantal driehoeken (inclusief nuloppervlak) zijn MC3 .

Opmerking: We moeten de punten zorgvuldig sorteren, kijk naar de cmp() functie bij de implementatie ter verduidelijking. 

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; } 

Uitgang:

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

Hulpruimte: O(maxy) waarbij maxy = 1000005



hernoem map linux