Forudsætninger: BIT Givet 'n' linjestykker er hver af dem enten vandret eller lodret, find det maksimale antal trekanter (inklusive trekanter med areal nul), der kan dannes ved at forbinde linjestykkernes skæringspunkter. Ingen to vandrette linjestykker overlapper og heller ikke to lodrette linjestykker. En linje er repræsenteret ved hjælp af to punkter (fire heltal, de første to er henholdsvis x- og y-koordinaterne for det første punkt og de to andre er x- og y-koordinaterne for det andet punkt) Eksempler:
javascript if-erklæring
| ---|-------|-- | | ----- | --|--|- | | | | 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 baseret på Sweep Line Algoritme . Opbygning af en løsning i trin:
- Gem begge punkter i alle linjestykker med den tilsvarende hændelse (beskrevet nedenfor) i en vektor og sorter alle punkterne i ikke-faldende rækkefølge efter deres x-koordinater.
- Lad os nu forestille os en lodret linje, som vi fejer henover alle disse punkter og beskriver 3 hændelser baseret på hvilket punkt vi i øjeblikket er:
- -en lodret linje
- Vi kalder regionen 'aktiv' eller de vandrette linjer 'aktiv' der har haft den første begivenhed, men ikke den anden. Vi vil have en BIT (Binært indekseret træ) til at gemme 'y'-koordinaterne for alle aktive linjer.
- Når en linje bliver inaktiv, fjerner vi dens 'y' fra BIT.
- Når en begivenhed af tredje type opstår, dvs. når vi er på en lodret linje, forespørger vi træet inden for rækkevidde af dets 'y'-koordinater og tilføjer resultatet til antallet af skæringspunkter indtil videre.
- Til sidst vil vi have antallet af skæringspunkter at sige m så vil antallet af trekanter (inklusive nulareal) være mC3 .
i - punkt længst til venstre i et vandret linjestykkeud - punkt længst til højre i et vandret linjestykkeNote: Vi er nødt til omhyggeligt at sortere punkterne se på cmp() funktion i implementeringen til afklaring.
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; } Produktion:
tilføje til array java
Number of triangles are: 4
Time Complexity: O( n * log(n) + n * log(maximum_y) )
Auxiliary Space: O(maxy) hvor maxy = 1000005