이번 포스팅에서는 백준 온라인 저지의 4225번 문제인 **‘쓰레기 슈트’**를 해결해보겠다. 이 문제는 기하학적인 접근이 필요한 문제로, 다각형이 회전하여 통과할 수 있는 최소 너비의 슈트를 계산하는 문제이다. Convex Hull과 Rotating Calipers 알고리즘을 활용하여 효율적으로 해결할 수 있다.
문제 : https://www.acmicpc.net/problem/4225
문제 설명
선영이는 빌딩에 설치할 쓰레기 슈트의 최소 너비를 구하려고 한다. 쓰레기 슈트는 일정한 너비를 가진 속이 빈 튜브로, 물체를 상단에 넣으면 회전하지 않고 일직선으로 떨어진다. 물체는 슈트에 들어갈 수 있도록 회전시킬 수 있지만, 슈트 내부에서는 회전하지 않는다.
물체는 2차원 다각형으로 모델링되며, 선영이는 이 다각형이 통과할 수 있는 가장 작은 슈트의 너비를 구하고자 한다. 슈트의 너비는 최소화되어야 하며, 이는 물체를 적절히 회전시켜 슈트를 통과시킬 수 있는 최소 너비를 찾는 문제로 귀결된다.
입력은 여러 개의 테스트 케이스로 구성되며, 각 테스트 케이스는 다각형의 꼭짓점의 개수와 각 꼭짓점의 좌표로 주어진다. 출력은 각 테스트 케이스마다 물체가 통과할 수 있는 최소 슈트의 너비를 소수점 둘째 자리까지 올림하여 출력한다.
접근 방식
이 문제는 주어진 다각형이 회전하여 통과할 수 있는 최소 너비를 구하는 기하학 문제이다. 이를 해결하기 위해 다음과 같은 알고리즘과 방법을 사용한다:
Convex Hull 계산: 다각형의 Convex Hull을 계산한다. Convex Hull은 다각형의 외곽을 감싸는 최소한의 볼록 다각형으로, 물체의 회전과 관계없이 최소 너비를 구하는 데 유용하다.
Rotating Calipers 알고리즘: Convex Hull의 각 변에 대해 수직 방향으로 물체를 투영하여 최소 너비를 구한다. 이때, Rotating Calipers 알고리즘을 사용하여 모든 가능한 방향에 대해 효율적으로 최소 너비를 계산한다.
최소 너비 계산: 각 투영 방향에서의 최대 거리 차이를 계산하여 그 중 최소 값을 선택한다.
시간 복잡도는 Convex Hull 계산에 O(N log N), Rotating Calipers 알고리즘에 O(N)이므로 전체 알고리즘은 O(N log N)이다.
C++ 코드와 설명
|
|
코드 설명
Point 구조체: 2차원 좌표를 표현하며, 벡터 연산과 비교 연산자를 오버로딩하였다.
convexHull 함수: Andrew’s Monotone Chain 알고리즘을 사용하여 Convex Hull을 계산한다. 점들을 x좌표, y좌표 순으로 정렬한 후 하단과 상단 Convex Hull을 각각 계산한다.
minimalWidth 함수: Convex Hull의 각 변에 대해 수직 벡터를 계산하고, 그 방향으로 모든 점을 투영하여 최대값과 최소값의 차이인 너비를 계산한다. 모든 변에 대해 최소 너비를 갱신한다.
roundUpTo0p01 함수: 계산된 최소 너비를 소수점 둘째 자리까지 올림한다.
main 함수: 입력을 받아 Convex Hull과 최소 너비를 계산하고 형식에 맞게 출력을 한다.
C++ without library 코드와 설명
|
|
코드 설명
라이브러리 제한:
stdio.h
만 사용하여 구현하였다.math.h
나stdlib.h
를 사용하지 않고 필요한 함수를 직접 구현하였다.fabs 함수: 실수의 절댓값을 계산하는 함수를 직접 구현하여
fabs
대체.quicksort 함수:
qsort
를 사용할 수 없으므로, 직접 QuickSort 알고리즘을 구현하여 점들을 정렬하였다.sqrt 함수:
sqrt
함수를 사용할 수 없으므로, Newton-Raphson 방법을 사용하여 제곱근을 계산하는 함수를 구현하였다.roundUpTo0p01 함수:
ceil
함수를 사용할 수 없으므로, 직접 올림 처리를 하는 함수를 구현하였다.convexHull 함수: Andrew’s Monotone Chain 알고리즘을 사용하여 Convex Hull을 계산하였다.
minimalWidth 함수: Convex Hull의 각 변에 대해 수직 벡터를 계산하고, 해당 방향으로 투영하여 최소 너비를 구하였다.
main 함수: 입력을 받고 Convex Hull과 최소 너비를 계산하여 결과를 출력한다..
Python 코드와 설명
|
|
코드 설명
Point 클래스: 2차원 좌표를 나타내며, 벡터 연산과 비교 연산자를 오버로딩하였다.
convexHull 함수: 점들을 정렬한 후 Convex Hull을 계산한다.
minimalWidth 함수: Convex Hull의 각 변에 대해 수직 벡터를 계산하고, 해당 방향으로 투영하여 최소 너비를 구한다.
roundUpTo0p01 함수: 최소 너비를 소수점 둘째 자리까지 올림한다.
main 함수: 표준 입력으로부터 데이터를 받아 처리하고 결과를 출력한다.
결론
이 문제는 기하 알고리즘 중 Convex Hull과 Rotating Calipers를 활용하여 효율적으로 해결할 수 있었다. 회전 가능한 다각형의 최소 너비를 구하는 것은 실세계에서도 중요한 문제이며, 이러한 알고리즘의 적용 가능성을 확인할 수 있었다. 또한, 부동 소수점 연산에서의 오차를 고려하여 EPS를 사용하고, 출력 형식에 맞게 올림 처리하는 것의 중요성을 다시 한번 느꼈다. 추가적으로, 다양한 프로그래밍 언어로 구현해 봄으로써 알고리즘의 이해도를 높일 수 있었다.