본문으로 건너뛰기
김신건의 로그

볼록 껍질 (Convex Hull)

· 수정 · 📖 약 4분 · 1,029자/단어 #algorithm #geometry #convex-hull
convex hull, 볼록 껍질, convex-hull, Andrew monotone chain, Graham scan

정의

볼록 껍질 (Convex Hull) 은 주어진 점 집합 P 를 모두 포함하는 최소 크기의 볼록 다각형. 즉 P 의 어떤 점도 다각형 외부에 있지 않고, 다각형의 꼭짓점은 P 의 일부 점.

표기: CH(P)

문제 상황과 동기

N 개의 2D 점이 흩어져 있을 때 이들을 모두 감싸는 최소 볼록 다각형을 찾는다.

  • Naive: 모든 점 쌍에 대해 직선을 긋고, 모든 점이 한쪽에 있는지 검사. O(N^3).
  • Graham scan (O(N log N)): 각도 정렬 후 스택.
  • Andrew’s monotone chain (O(N log N)): x 좌표 정렬 후 상단 / 하단 hull 따로 구성. 구현이 더 간결.

핵심 통찰: 볼록 껍질은 볼록 다각형의 모든 꼭짓점이 CCW 방향을 만족한다. 스택에 넣고 CCW 조건이 깨지면 pop.

시각화

핵심 아이디어

CCW 판정

ccw(a, b, c) = (b - a) x (c - a)
             = (b.x - a.x)*(c.y - a.y) - (b.y - a.y)*(c.x - a.x)
> 0  -> 반시계 (좌회전)
< 0  -> 시계 (우회전)
= 0  -> 일직선

볼록 껍질에서는 모든 인접 세 점이 일관된 방향 (시계 또는 반시계) 을 유지.

Andrew’s Monotone Chain (가장 널리 사용)

1. 점들을 x (같으면 y) 오름차순 정렬          // O(N log N)
2. Lower hull: 왼->오 sweep 하면서 ccw <= 0 이면 pop
3. Upper hull: 오->왼 sweep 하면서 ccw <= 0 이면 pop
4. 합치기 (중복 끝점 제거)

invariant: 스택의 마지막 두 점과 새 점이 항상 ccw > 0 (또는 < 0) 을 만족.

알고리즘

andrew_monotone_chain(P):
    sort(P)                         // x, y 기준
    lower = []
    for p in P:
        while len(lower) >= 2 and ccw(lower[-2], lower[-1], p) <= 0:
            lower.pop()
        lower.append(p)
    upper = []
    for p in reversed(P):
        while len(upper) >= 2 and ccw(upper[-2], upper[-1], p) <= 0:
            upper.pop()
        upper.append(p)
    return lower + upper[1:-1]      // 끝점 중복 제거

구현

// Andrew's monotone chain O(N log N)
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
struct Point { ll x, y; };
ll ccw(Point a, Point b, Point c) {
  return (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
}
vector<Point> convex_hull(vector<Point>& p) {
  sort(p.begin(), p.end(), [](auto& a, auto& b) {
      return a.x < b.x || (a.x == b.x && a.y < b.y);
  });
  vector<Point> hull;
  auto build = [&](int start, int end, int sign) {
      for (int i = start; i != end; i += (end - start > 0 ? 1 : -1)) {
          while ((int)hull.size() - start >= 2) {
              auto& a = hull[hull.size() - 2];
              auto& b = hull.back();
              if (ccw(a, b, p[i]) * sign > 0) break;
              hull.pop_back();
          }
          hull.push_back(p[i]);
      }
  };
  build(0, p.size(), 1);           // lower
  int lower_sz = hull.size();
  build(p.size() - 2, -1, 1);      // upper (끝점 제외)
  hull.pop_back();                 // 시작점 중복 제거
  return hull;
}
int main() {
  vector<Point> pts = {{0,0},{1,1},{2,0},{1,-1},{0,1}};
  auto hull = convex_hull(pts);
  cout << "Convex Hull:\n";
  for (auto& p : hull)
      cout << "(" << p.x << ", " << p.y << ")\n";
}
결과
Convex Hull:
(0, 0)
(0, 1)
(1, 1)
(2, 0)
(1, -1)

복잡도

항목
시간 (Andrew / Graham)O(N log N) (정렬이 지배)
시간 (정렬 후)O(N) (스택 sweep)
공간O(N) (결과 hull)
안정성- (유일 결정)

동일 점 (중복) 은 정렬 후 제거. Collinear (일직선) 점은 hull 에 포함할지 말지 선택.

변형 / 활용

1. Graham Scan

각도 정렬 (atan2) 후 같은 로직. Andrew 가 ssqrt 없고 실수 오차가 없어 더 선호됨.

2. Convex Hull Trick (CHT)

y = m*x + b 직선 중 특정 x 에서 최댓값. Convex hull (lower envelope) 과 동형.

3. 동적 Convex Hull

점이 추가/삭제될 때 hull 유지. O(log N) 갱신. (Overmars / Van Leeuwen 트리)

4. 3D Convex Hull

QuickHull O(N log N). 결과는 삼각형 메시 (face).

5. Rotating Calipers, 최근접 점 쌍, 최대 면적 삼각형

hull 위에서 O(N) 으로 각종 최적화.

함정

1. Collinear 처리

ccw <= 0 조건으로 collinear 점을 pop 하면 hull 변 가장자리 위의 점이 제외됨. 모든 collinear 점을 포함하려면 ccw < 0.

2. x 정렬만으로는 부족

x 가 같으면 y 정렬 필수. 안 하면 vertical line 에서 잘못된 hull.

3. Integer overflow

좌표 ±10^9 에서 (b.x - a.x) * (c.y - a.y)±4*10^18 까지 가능 -> C++ long long (64-bit). __int128 이 필요할 수 있음.

4. 점이 2개 이하

N ≤ 2 면 hull = 점들 그대로.

BOJ 연습 문제

번호제목정답률링크
BOJ 4181Convex Hull21.1%kokoa-lab
BOJ 3679단순 다각형26.2%kokoa-lab
BOJ 17058Convex Hull 연습39.1%kokoa-lab
BOJ 6850Cows42.5%kokoa-lab
BOJ 2254감옥 건설33.1%kokoa-lab

참고

이 글의 용어 (4개)
기하 (Geometry) 기본algorithm
정의 Computational Geometry 는 점, 선, 다각형 등 기하 객체를 컴퓨터로 처리하는 알고리즘 분야. PS 에서는 2D 평면 위의 정수 좌표 가 주로 다루어지며,…
회전 캘리퍼스 (Rotating Calipers)algorithm
정의 회전 캘리퍼스 (Rotating Calipers) 는 볼록 다각형 위에서 서로 마주보는 두 평행선 (겹지름, antipodal pair) 을 회전시키며 다각형의 최장 거리,…
CHT (Convex Hull Trick)algorithm
정의 Convex Hull Trick (CHT) 은 DP 전이 같이 선형식들의 lower envelope (또는 upper envelope) 에서 한 점 값을 평가하는 패턴을, …
Geometry Basic: 벡터, CCW, 외적, 내적algorithm
정의 기하 알고리즘의 밑바탕. 대부분의 2D/3D 기하 문제는 벡터 연산, 내적/외적, CCW 판정 세 가지의 조합으로 풀립니다. 벡터 2D 벡터: 두 점 $A = (ax, ay…

💬 댓글

사이트 검색 / 명령어

검색

스크롤 = 확대/축소 · 드래그 = 이동 · 0 = 원래 크기 · ESC = 닫기