logo

Finne antall trekanter mellom horisontale og vertikale linjestykker

Forutsetninger: BIT  Gitt 'n' linjestykker hver av dem er enten horisontale eller vertikale, finn det maksimale antallet trekanter (inkludert trekanter med null areal) som kan dannes ved å slå sammen skjæringspunktene til linjestykkene. Ingen to horisontale linjestykker overlapper og heller ikke to vertikale linjestykker. En linje er representert ved å bruke to punkter (fire heltall første to er x- og y-koordinatene henholdsvis for det første punktet og de to andre er x- og y-koordinatene for det andre punktet) Eksempler:

katalog i linux-kommandoer
 | ---|-------|-- | | ----- | --|--|- | | | | 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.

Ideen er basert på Sweep Line Algoritme . Bygge en løsning i trinn:



  1. Lagre begge punktene til alle linjestykker med den tilsvarende hendelsen (beskrevet nedenfor) i en vektor og sorter alle punktene i ikke-avtagende rekkefølge av deres x-koordinater.
  2. La oss nå forestille oss en vertikal linje som vi sveiper over alle disse punktene og beskriver 3 hendelser basert på hvilket punkt vi er for øyeblikket:
      i- punktet lengst til venstre i et horisontalt linjestykkeute- punktet lengst til høyre i et horisontalt linjestykke
    • en vertikal linje
  3. Vi kaller regionen 'aktiv' eller de horisontale linjene 'aktiv' som har hatt det første arrangementet, men ikke det andre. Vi vil ha en BIT (Binært indeksert tre) for å lagre 'y'-koordinatene til alle aktive linjer.
  4. Når en linje blir inaktiv, fjerner vi dens 'y' fra BIT.
  5. Når en tredje type hendelse inntreffer, det vil si når vi er på en vertikal linje, spør vi treet innenfor rekkevidden av dets 'y'-koordinater og legger resultatet til antallet skjæringspunkter så langt.
  6. Til slutt vil vi ha antall skjæringspunkter si m da vil antall trekanter (inkludert nullareal) være mC3 .

Note: Vi må nøye sortere punktene se på cmp() funksjon i gjennomføringen for avklaring. 

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

Produksjon:

java fangst prøve
Number of triangles are: 4
Time Complexity:   O( n * log(n) + n * log(maximum_y) )  

Auxiliary Space: O(maxy) hvor maxy = 1000005