※ 글쓴이는 취미로 코딩을 익혀보는 사람이라 정확하지 않은 내용을 담고 있을 수 있다 ※
이번에 볼 문제는 백준 26276번 문제인 Point in Triangle이다.
문제는 아래 링크를 확인하자.
https://www.acmicpc.net/problem/26276
26276번: Point in Triangle
좌표 평면상에 $N$개의 점이 있다. 이 중에서 3개의 점을 골라 만들 수 있는 삼각형 중 점 $P$를 내부에 완전히 포함하는 것의 개수를 구하시오. 점 $P$가 삼각형의 변에 놓인 경우는 세지 않는다.
www.acmicpc.net
편의상 점
좌표평면의 왼쪽에 있는 점 셋만을 이용하거나 오른쪽에 있는 점 셋만을 이용해서는 원점을 완전히 포함하는 삼각형을 만들 수 없음은 자명하다. 따라서 왼쪽에서 점을 하나, 오른쪽에서 점을 둘 고르는 경우와 왼쪽에서 점을 둘, 오른쪽에서 점을 하나 고르는 경우의 두 가지 경우만을 고려하면 문제를 해결할 수 있다. 이중 한 경우만 해결할 수 있어도 다른 경우 또한 같은 방법으로 해결할 수 있으므로, 아래에서는 오른쪽에서 한 점을 고르는 경우를 생각해보자.
위와 같이 점을 고르려 할 때 오른쪽에서 고른 점을
이를 모든 점에 대해 빠르게 계산하기 위해 점들을 기울기(각도)를 기준으로 정렬한 뒤 투포인터를 활용해 스위핑(sweeping)해주자.
위 과정에서 각 점과 원점 사이의 거리는 삼각형이 원점을 포함하는지 여부에 영향을 주지 않는다는 점을 관찰하자. 즉, 이 문제를 해결하는 데에 있어서 점의 정보를 저장할 때 거리를 제외한 원점을 기준으로 한 기울기(각도) 정보만을 보관해도 충분하다.
아래는 제출한 소스코드이다.
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pll;
int N;
ll X, Y;
vector<pll> LEFT, RIGHT;
bool comp(pll& l, pll& r) {
return l.second * r.first < r.second* l.first;
}
bool comp2(pll& l, pll& r) {
return l.second * r.first <= r.second * l.first;
}
ll ans;
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> N >> X >> Y;
while (N--) {
ll x, y; cin >> x >> y;
ll dx = x - X, dy = y - Y;
if (dx > 0) RIGHT.emplace_back(make_pair(dx, dy));
else if (dx < 0) LEFT.emplace_back(make_pair(-dx, -dy));
else if (dy > 0) RIGHT.emplace_back(make_pair(1, 2000000007));
else LEFT.emplace_back(make_pair(1, 2000000007));
}
sort(LEFT.begin(), LEFT.end(), comp);
sort(RIGHT.begin(), RIGHT.end(), comp);
ll idx1 = 0, idx2 = 0, sizeL = LEFT.size();
for (auto& p : RIGHT) {
while (idx1 < sizeL && comp(LEFT[idx1], p)) idx1++;
while (idx2 < sizeL && comp2(LEFT[idx2], p)) idx2++;
ans += idx1 * (sizeL - idx2);
}
idx1 = 0, idx2 = 0; ll sizeR = RIGHT.size();
for (auto& p : LEFT) {
while (idx1 < sizeR && comp(RIGHT[idx1], p)) idx1++;
while (idx2 < sizeR && comp2(RIGHT[idx2], p)) idx2++;
ans += idx1 * (sizeR - idx2);
}
cout << ans;
}
'BOJ' 카테고리의 다른 글
[BOJ 26043 // C++] 식당 메뉴 (0) | 2022.12.12 |
---|---|
[BOJ 26201 // C++] Finding Maximal Non-Trivial Monotones (0) | 2022.12.12 |
[BOJ 24084 // C++] 次の文字 (Next Character) (0) | 2022.12.12 |
[BOJ 26042 // C++] 식당 입구 대기 줄 (0) | 2022.12.12 |
[BOJ 16398 // C++] 행성 연결 (0) | 2022.12.12 |