
탐욕 알고리즘(greedy algorithm)은 매번 현재로써 최선인 선택을 "탐욕스럽게" 취하는 알고리즘 기법으로, 문제 해결 및 다양한 분야에서 활용되고 있습니다. 알고리즘의 동작이 매우 단순하기 때문에 상대적으로 간단히 구현할 수 있으며 매우 빠른 시간에 수행된다는 장점이 있죠. 하지만 반대로 탐욕 알고리즘이 최적해를 출력한다는 것을 보이는 것은 매우 어려운데요. 직관적으로는 매우 그럴 것 같지만 막상 그것을 증명하려고 하면 까다롭기 때문입니다.
이번 시간에는 분석하기 어려운 탐욕 알고리즘을 분석하는 일반적인 기법들을 몇 가지 소개해 보도록 하겠습니다. 구체적으로
- Greedy stays ahead
- Certificate argument
- Exchange argument
를 다룰 예정입니다. 각 기법에 대한 간단한 설명과 더불어 실제 백준 온라인 저지의 문제들을 통해 각 기법이 어떻게 적용되는지 살펴볼 것입니다.
개인적으로 포스팅할 때 영어로 된 명칭은 최대한 번역해보려고 노력합니다만, 이번에는 그게 너무 힘들어서 그냥 원래 이름을 그대로 사용하였습니다. 모쪼록 양해를 바랍니다.
Greedy Stays Ahead : 탐욕스러운 것이 항상 좋을 지니...

첫 번째 기법은 'greedy stays ahead'입니다. 직역하자면, "탐욕 알고리즘이 항상 앞선다." 정도가 되겠습니다. 이 기법은 탐욕 알고리즘을 증명하는 다른 기법들에 비해 상대적으로 쉽고 간단합니다. 이것이 의미하는 바를 좀더 잘 이해하기 위해서는 다음과 같은 상황을 생각해 보면 좋습니다. 먼저 최적해를 출력하는 가상의 알고리즘을 하나 가지고 오도록 하겠습니다. 그러고는 최적 알고리즘이 매번 선택을 할 때 탐욕 알고리즘이 어떤 선택을 하는지 살펴보겠습니다. 만약 탐욕 알고리즘의 선택이 최적 알고리즘의 선택보다 항상 (어떤 기준에 따라) 좋다면, 전체적으로 봤을 때도 탐욕 알고리즘의 출력이 최적 알고리즘의 그것보다 좋다고 보일 수 있습니다. 그러니 탐욕 알고리즘이 내놓은 답이 최적해가 되는 것이죠.
구체적인 예시로 다음 문제를 생각해 봅시다. 우리는 여러 작업들을 처리해야 하며, 이를 위해 기계가 달랑 하나 주어졌습니다. 각 작업은 시작 시각과 끝 시각을 가지며, 만약 한 작업을 기계에 넣어 처리하려고 한다면, 해당 시작 시각부터 끝 시각까지는 다른 작업을 처리할 수 없습니다. 대신 한 작업이 끝나는 시각에 시작하는 작업은 곧바로 기계에 할당할 수 있습니다. 우리의 목표는 최대한 많은 수의 작업을 처리하는 것입니다. 아실 분들은 아실 테지만, 이 문제는 유명한 인터벌 스케줄링(interval scheduling)이며 백준 온라인 저지에도 이에 해당하는 [BOJ 1931] 회의실배정 문제가 있습니다.
이 문제를 해결하는 잘 알려진 알고리즘은 다음과 같습니다.
모든 작업을 끝나는 시각의 오름차순으로 정렬한 후, 각 작업을 순서대로 고려하면서 기계에 할당할 수 있으면 넣고 그렇지 않으면 버린다.
이 알고리즘을 시각화하면 다음 그림과 같이 됩니다.

처음 보시는 분들이라면 "이게 정말 되는 거 맞아?"라고 생각하실 수 있겠습니다. 매우 좋은 반응입니다. 알고리즘을 공부하실 때는 비판적인 시각을 견지하는 것이 매우 중요합니다. 그리고 놀랍게도, 이 알고리즘은 실지로 최적해를 출력하는 알고리즘입니다. 그에 대해 직관적인 설명을 먼저 해 보겠습니다. 모든 작업을 끝나는 시각으로 정렬하고 그 순서대로 고려한다는 것은 먼저 끝나는 작업부터 기계에 할당하겠다는 의미입니다. 그러면 작업이 끝난 후 다른 작업을 처리할 수 있는 시간이 더 길어지기 때문에 좋을 것으로 예상됩니다.
하지만 증명하기 전까지는 그 생각이 올바른지 아무도 모릅니다. 그러니 증명해 보도록 하죠. 증명을 편히 하기 위해서 몇 가지 기호들을 정의하고 넘어가겠습니다. 먼저 어떤 작업
우리가 보이고 싶은 것은
정리 1. Correctness by greedy-stays-ahead
모든
이것이 말하는 바를 먼저 설명 드리자면, 최적해의 각
[정리 1 증명]
이제

남은 것은

Certificate Argument : 이것이 내 답이 정답이라는 증거일세!

다음 기법으로 넘어 가도록 하겠습니다. 이번에 공부할 기법은 'certificate argument'입니다. 직역하자면 '증거 논의' 쯤 되겠는데요. 이 기법은 알고리즘이 답과 함께 그 답이 최적해라는 증거를 함께 출력하도록 만드는 방법입니다. 증거를 함께 제출했으니 무엇을 더 바랄까요?
바로 예시를 들어 보겠습니다. 이번 문제는 앞에서 본 문제의 변형입니다. 똑같이 우리에게 여러 작업들이 주어지며 우리는 이 작업들을 기계에 돌려 처리해야 합니다. 이번에는 기계를 여러 대 구매할 수 있습니다만 대신 모든 작업을 처리해야 합니다. 과연 모든 작업을 처리하기 위해서는 최소 몇 대의 기계가 필요하고, 작업들을 기계에 어떻게 할당해야 할까요? 이 문제는 백준 온라인 저지의 [BOJ 11000] 강의실 배정을 다르게 표현한 것입니다.
기호를 사용하여 문제를 좀더 간략히 표현해 보겠습니다. 우리에게는 작업의 집합
- 각
는 서로 겹치는 작업이 없는 의 부분집합이다. 즉, 임의의 서로 다른 두 작업 에 대해, 이다.
알고리즘을 소개하기에 앞서 한 가지 생각해 봅시다. 과연 우리는 최소한 몇 대의 기계가 필요할까요? 네, 모든 작업을 수행해야 하므로 어떤 시각에 동시에 수행되는 작업의 개수보다는 적지 않아야 합니다. 다시 말해, 어떤 시각
정리 2. Certificate
이 정리가 흥미로운 이유는 다음 정리를 이끌어낼 수 있기 때문인데요.
정리 3. Optimality through certificate
만약 알고리즘이 올바른 답
[증명] 문제의 최적해를
다시 말해, 알고리즘이
시간의 흐름에 따라 다음을 고려한다. 매 시각에 시작하는 작업이 있을 때 지금까지 구매한 기계에 할당할 수 있으면 그것들 중 아무 것에 할당한다. 현재까지 구매한 기계만으로는 불가능하다면, 기계를 하나 더 구매하고 거기에 할당한 다음 를 기억한다.
이를 시각화하면 다음 그림과 같습니다.

매 시각마다
Exchange Argument : 봐봐, 이렇게 저렇게 바꾸면 내 답이랑 똑같지?

마지막으로 살펴볼 증명 기법은 'exchange argument'입니다. 직역하자면 '교환 논의' 정도가 되겠는데요. 이 방법은 먼저 가상의 최적해를 하나 고정하고, 이 최적해를 약간씩 수정하여 알고리즘의 답과 동일하도록 만드는 것입니다. 여기서 매번 최적해를 수정할 때 답이 나빠지지 않는다는 것을 보인다면 최종적으로 알고리즘의 답이 최적해보다 나쁘지 않다는 것을 보이게 되어, 그 답 역시 최적해라는 것을 증명하게 되는 것이죠.
이번 예시는 [BOJ 14464] 소가 길을 건너간 이유 4입니다. 대신 일관되도록 표현하기 위해 기계와 작업으로 바꿔 설명하겠습니다. 여전히 우리에게는 처리해야 할 작업들이 주어집니다. 이번 작업들에는 생성 시각과 마감 시각이 주어집니다. 즉, 생성되기 전에는 작업을 처리할 수 없으며, 작업이 생성된 후 마감 시각이 되기 전까지 작업을 기계에 할당하지 못하면 작업은 처리되지 못합니다.
이번에는 기계를 구매하여 작업을 처리하지 않고 외부의 공용 기계를 사용하려고 합니다. 그런데 이 공용 기계가 동작하는 방식이 약간 특이한데, 특정한 시각에 최대 하나의 작업을 처리할 수 있다고 우리에게 신호를 주게 됩니다.
정리하면, 언젠간 공용 기계가 우리에게 작업을 진행할 수 있다고 연락을 주면, 우리는 그 때 처리 가능한 작업 하나를 공용 기계에 보내는 방식으로 작업을 처리하게 됩니다. 다행히도 이번에는 외부 기계를 사용하기 때문에 작업들의 수행 시간이 겹치는 문제는 고민할 필요가 없습니다. 그건 공용 기계 쪽에서 알아서 처리할 문제죠. 우리의 목표는 최대한 많은 작업을 공용 기계에 보내 처리하는 것입니다.
이제 이 문제를 해결하는 알고리즘을 구상해 봅시다. 매번 공용 기계로부터 신호를 받으면 가능한 작업 중 하나를 공용 기계로 보낼 수 있습니다. 어떤 작업을 보내는 것이 좋을까요? 아무래도 곧 마감되는 작업을 보내는 것이 이득일 것입니다. 마감 시각이 이르다면 곧 마감되어 더 이상 작업을 처리하지 못하게 될 수 있는 반면, 마감이 늦으면 그만큼 다른 신호를 받아 처리할 가능성이 높다는 것을 의미하니까 말이죠. 따라서 이런 알고리즘을 만들어 보겠습니다.
매번 공용 기계로부터 신호를 받으면 처리할 수 있는 작업 중 가장 마감 시각이 이른 것을 공용 기계로 전송한다. 만약 처리할 수 있는 작업이 존재하지 않는 경우에는 아무 행동도 하지 않는다.
이를 도식화하면 다음과 같습니다.

아이디어는 매우 그럴듯하지만 증명되지 않은 명제는 주장일 뿐이죠. 이제부터 이 알고리즘이 항상 최적해를 출력한다는 것을 exchange argument로 증명해 보도록 하겠습니다.
증명을 위해 주어진 문제를 기호로 표현해 보겠습니다. 우리에게는 작업의 집합
- 임의의 작업-신호 쌍
은 를 만족한다. - 임의의 작업
나 어떤 신호 시각 나 에는 최대 한 번만 등장한다. 예를 들어, 에 대해서 이면서 동시에 일 수 없으며, 에 대해 동시에 과 일 수 없다.
우리의 목표는 그러한
위 탐욕 알고리즘이 출력한 결과를
구체적으로 설명드리기 전에 몇 가지 정의와 가정이 필요합니다. 먼저
우리의 목표는 다음 정리를 증명하는 것입니다.
정리 4. Exchange operation
다음을 만족하는
이다.- 임의의
에 대해, 까지 와 는 동일하다. 즉, 각 에 대해, 이다. 이다.
특히, 두 번째 조건에 의해
[증명]
경우 1.
경우 2.
경우 3.

그렇지 않은 경우,
경우 4.

만약

마지막으로
모든 경우에 대해서, 정리의 조건을 만족하는
마치며
이번 포스트에서는 탐욕 알고리즘을 증명하는 세 가지 증명 기법에 대해서 알아 보았습니다. 간단히 정리하면 다음과 같습니다.
- Greedy stays ahead는 매번 탐욕 알고리즘이 선택하는 것이 가상의 최적 알고리즘이 선택하는 것보다 항상 좋다는 것을 보임으로써 증명하는 기법입니다.
- Certificate argument는 알고리즘이 답을 출력할 때, 그 답이 실제로 최적해라는 증거를 함께 제출하는 기법입니다.
- 마지막으로 exchange argument는 최적해를 조금씩 바꾸어 탐욕 알고리즘의 답과 동일하게 만들되, 매번 나빠지지 않는다는 것을 보임으로써 알고리즘의 답이 최적해라는 것을 증명하는 방법입니다.
모든 탐욕 알고리즘이 이 기법을 활용해서 증명할 수 있는 것은 아닙니다만, 많은 경우 세 가지 기법을 적용하면 알고리즘이 정확히 동작한다는 것을 증명할 수 있습니다.
이것으로 글을 모두 마칩니다. 궁금하신 점이 있으시거나, 글에 잘못된 내용이 적혀있는 경우에는 댓글로 알려주시기 바랍니다. 고맙습니다. :)
'알고리즘 기초 > Algorithm design' 카테고리의 다른 글
분할 상환 분석 (Amortized Analysis) (8) | 2021.04.08 |
---|