먼저 정점을 일정 방향으로 (보통 시계 반대방향) 으로 정렬을 해야한다. 이는 가장 구석에 있는 정점을 기준으로 CCW() 를 써서 비교하면 된다.
구석에 있는 정점을 찾는 이유는 기준점이 정점들의 중앙에 있으면 대소관계가 순환을 이룰 수 있기 때문이다.
만약 CCW() 가 0이라면, 즉 세 점이 같은 직선 위에 놓여져 있다면, 기준점과의 거리를 사용해 대소관계를 정의한다.
위에선 CCW(base, a, b) 가 양수일 때 a < b 이므로, a - base 기준으로 b 가 왼쪽에 있다면 a < b 이다. 다시말해 기준점 기준으로 시계반대방향 순으로 정렬이 된다. 따라서 CCW() == 0 인 경우 거리가 짧은걸 먼저 오게 해야한다.
다음 단계는 일정 방향으로(여기선 시계 반대방향) 정렬된 정점을 하나씩 살펴가면서 다른 정점을 포함하는 최외곽 정점들을 찾아야한다. 이는 스택을 사용해 구할 수 있다.
먼저 두 정점을 넣어 놓는다. 그리고 스택 위의 두개의 점과 정렬된 정점목록을 비교한다.
스택 위에 차례로 a, b 가 있어서 b - a 를 기준으로 새로 비교하는 정점 c 가 왼쪽/오른쪽에 있는지 CCW(a, b, c) 로 알 수 있다. 만약 이 값이 0보다 크면(왼쪽에 있으면) 스택에 추가한다. 만약 작다면(오른쪽에 있으면) 새로나온 c 를 a 로 대체할 수 있다. c 가 왼쪽에 올 때까지 스택을 비워내고 c 를 추가한다.
스택에 들어오는 정점은 정점의 갯수를 넘을 수 없으므로 선형복잡도를 가지게 된다.
Rotating Calipers
펼치기
코드
설명
위는 이 문제를 푸는 코드이다. 이 알고리즘을 적용할 수 있는 영역이 굉장히 많으므로 Wiki 의 관련 챕터를 한번 읽어보자.
댓글남기기