ในบทความนี้ เราจะพูดถึงโปรแกรมเพื่อหาจำนวนสามเหลี่ยมที่สามารถเกิดขึ้นได้โดยการรวมจุดตัดกันของส่วนของเส้นแนวนอนและแนวตั้งที่กำหนด
ตัวอย่างเช่น สมมติว่าเราได้รับส่วนของเส้นตรงต่อไปนี้ ในนี้เรามีจุดตัดกัน 3 จุด ดังนั้นจำนวนสามเหลี่ยมที่สามารถเกิดขึ้นได้โดยใช้จุดเหล่านี้จะเป็น 3 C2 .
| ---|--------|-- | | | --|---| | |
เราจะทำตามอัลกอริธึม Sweep Line เราจะจัดเก็บค่าทั้งหมดของส่วนของเส้นตรง จากนั้นตรวจสอบว่าจุดภายในเส้นใดเส้นหนึ่งนั้นเปรียบเทียบกับจุดภายในของเส้นอื่นๆ หรือไม่ ด้วยวิธีนี้ เราจะมีจุดตัดกันทั้งหมดสำหรับส่วนของเส้นตรงที่กำหนด จากนั้นเราสามารถหาจำนวนสามเหลี่ยมที่เป็นไปได้ได้อย่างง่ายดายโดยใช้ชุดค่าผสมต่างๆ ที่เป็นไปได้
ตัวอย่าง
#include<bits/stdc++.h> #define maxy 1000005 #define maxn 10005 using namespace std; //to store intersection points struct i_point { int x, y; i_point(int a, int b) { x = a, y = b; } }; int bit[maxy]; vector < pair <i_point, int> > events; //to sort the given points bool com_points(pair<i_point, int> &a, pair<i_point, int> &b) { if ( a.first.x != b.first.x ) return a.first.x < b.first.x; else { if (a.second == 3 && b.second == 3) { return true; } else if (a.second == 1 && b.second == 3) { return true; } else if (a.second == 3 && b.second == 1) { return false; } else if (a.second == 2 && b.second == 3) { return false; } return true; } } void topdate_line(int index, int value) { while (index < maxn) { bit[index] += value; index += index & (-index); } } int query(int index) { int res = 0; while (index > 0) { res += bit[index]; index -= index & (-index); } return res; } //to insert a line segment void insertLine(i_point a, i_point b) { //in case of horizontal line if (a.y == b.y) { int begin = min(a.x, b.x); int end = max(a.x, b.x); events.push_back(make_pair(i_point(begin, a.y), 1)); events.push_back(make_pair(i_point(end, a.y), 2)); } //in case of vertical line else { int top = max(b.y, a.y); int bottom = min(b.y, a.y); events.push_back(make_pair(i_point(a.x, top), 3)); events.push_back(make_pair(i_point(a.x, bottom), 3)); } } //to calculate number of intersection points int calc_i_points() { int i_points = 0; for (int i = 0 ; i < events.size() ; i++) { if (events[i].second == 1) { topdate_line(events[i].first.y, 1); } else if (events[i].second == 2) { topdate_line(events[i].first.y, -1); } else { int bottom = events[i++].first.y; int top = events[i].first.y; i_points += query(top) - query(bottom); } } return i_points; } int calc_triangles() { int points = calc_i_points(); if ( points >= 3 ) return ( points * (points - 1) * (points - 2) ) / 6; else return 0; } int main() { insertLine(i_point(3, 2), i_point(3, 13)); insertLine(i_point(1, 5), i_point(3, 5)); insertLine(i_point(8, 2), i_point(8, 8)); insertLine(i_point(3, 4), i_point(6, 4)); insertLine(i_point(4, 3), i_point(4, 5)); sort(events.begin(), events.end(), com_points); cout << "Possible number of triangles : " << calc_triangles() << endl; return 0; }
ผลลัพธ์
Possible number of triangles : 1