BOJ 2166
Posted on 2022-12-05 by GKSRUDTN99
Problem Solving
BOJ
Geometry
다각형의 면적
문제를 푸는 데 필요한 배경지식
1. 두 벡터의 외적
2. cout 소수점 자리수 고정
3. 세 점이 이루는 삼각형의 넓이
점 A, B, C가 이루는 삼각형의 넓이는 AB벡터와 AC벡터의 외적을 통해 구할 수 있습니다.
AB벡터와 AC벡터의 외적의 크기는 AB벡터의 AC벡터를 두 변으로 하는 평행 사변형의 넓이와 같으므로,
외적 크기 / 2를 통해 삼각형의 넓이를 구할 수 있습니다.
문제 풀이
3개 이상의 점들이 다각형을 이루는 순서대로 입력으로 주어집니다.
N개의 점들()이 이루는 다각형이 볼록 다각형인 경우,
i 번째 점을 입력 받을 때 를 계산하여 세 점 가 이루는 삼각형의 면적을 다 더해주면 다각형의 면적이 됩니다.
만약 N개의 점들이 이루는 다각형이 볼록 다각형이 아닌 경우, 볼록껍질에 포함되지 않는 점이 입력으로 들어왔을 때 를 계산해보면, 볼록껍질에 포함되는 점에 대한 외적 결과값과는 부호가 반대가 되는 것을 확인할 수 있습니다.
볼록껍질에 포함되지 않는 점가 시작점과 과 이루는 삼각형은 다각형의 면적을 구할 때 더해지는 것이 아니라, -로 빼줘야 다각형의 면적을 구할 수 있습니다.
아래 그림의 경우, 초록색 면적은 더하고, 붉은색 면적을 빼면 전체 다각형의 넓이를 구할 수 있습니다.
위 두가지 경우를 모두 고려하기 위해, 삼각형의 넓이를 구할 때 사용하는 외적의 결과값에 절대값을 취하지 않고, 모두 더한 뒤에, 마지막에만 절대값을 취해주면 답을 구할 수 있습니다.
절대값을 취해야 하는 이유는, 입력이 다각형의 시작점을 기준으로 시계 방향으로 들어올 지, 반시계 방향으로 들어올 지 알 수 없기 때문입니다.
풀이 코드
#include <bits/stdc++.h>
#define INF 999999999999
typedef long long ll;
using namespace std;
ll n;
double area;
struct Point {
ll x;
ll y;
};
double cross_product(Point a, Point b, Point c) {
return a.x * b.y + b.x * c.y + c.x * a.y - b.x * a.y - c.x * b.y - a.x * c.y;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(0);
cout.setf(ios::fixed);
cout.precision(1);
cin >> n;
Point start, last, now;
cin >> start.x >> start.y;
cin >> last.x >> last.y;
for(ll i = 2; i < n; i++) {
cin >> now.x >> now.y;
area += cross_product(start, last, now) / 2;
last = now;
}
cout << abs(area);
return 0;
}