[1. 개요]
탐욕법은 가장 직관적인 알고리즘 설계 패러다임 중 하나이다.
각 단계마다 답의 한 부분을 만들어 간다는 점에서
완전 탐색이나 동적 계획법 알고리즘과 다를 것이 없으나,
각 단계마다 지금 당장 가장 좋은 방법만을 선택한다는 것이 다르다.
그래서, 지금의 선택이 앞으로 남은 선택들에 어떤 영향을 끼칠지는 고려하지 않는다.
탐욕법으로 최적해를 찾을 수 있는 많은 문제들은 동적 계획법으로도 풀 수 있다.
=> 모든 단계를 고려하는 동적 계획법이 틀릴 이유가 없기 때문
그럼에도, 탐욕법을 사용하는 이유는 동적 계획법에 필요한 메모리나 시간이 너무 크기 때문이다.
탐욕적 알고리즘을 설계하는 좋은 방법은
간단한 입력을 몇 개 손으로 풀어 보면서 패턴을 찾는 것
[2. 사용되는 경우]
A. 탐욕법을 사용해도 항상 최적해를 구할 수 있는 문제인 경우
=> 동적 계획법보다 수행 시간이 훨씬 빠르다.
B. 시간/공간적 제약으로 인해 최적해를 찾기 어려운 경우, 적당히 괜찮은 값(근사값) 을 찾고자 하는 경우
알고리즘 문제에서는 A 인 경우로만 사용된다고 볼 수 있다.
그래서 여러개의 탐욕적인 방법 중 어느 방법을 선택해야 최적해를 구할 수 있을지를 알아내기가 어렵다.
=> 알고리즘의 정당성을 증명하는 과정을 연습해야 한다.
[3. 정당성 증명]
예제) 각각의 회의 시간이 주어지고,
서로 겹치지 않는 회의들만을 골라낼 때, 최대 몇개나 선택할 수 있는가?
- 완전 탐색 풀이
=> 집합의 크기가 n 일 때, 부분 집합의 개수는 2^n 이므로 시간 제한에 걸린다.
=> 재귀적인 방법으로 부분 집합을 만듬
==> 각 단계마다 회의 A 를 선택하는 경우와 선택하지 않는 경우... - 탐욕 알고리즘
= 오답 => 길이가 짧은 회의 부터 선택
==> 반례, A: [0, 5], B: [5, 10], C: [4, 6] 일 때, C 를 선택하면 A, B 는 회의를 진행하지 못한다.
==
= 정답 => 길이와 상관 없이 가장 먼저 끝나는 회의부터 선택한다.
위 탐욕 알고리즘의 정당성 증명과정
=> 탐욕 알고리즘 정당성 증명은 많은 경우 일정한 패턴을 갖는다.
=> 이 패턴은, 탐욕 알고리즘이 항상 최적해를 찾아낼 수 있다는 것을 두 가지의 속성을 증명하여 보인다.
탐욕적 선택 속성
위 속성이 성립할 경우, 각 단계에서 탐욕적인 선택을 해서 손해 볼 일이 없다는 것을 알 수 있다.
== 가장 종료 시간이 빠른 회의(Smin)를 포함하는 최적해(S)가 반드시 존재한다.
- S 의 최적해 중, Smin 을 포함하지 않는 답이 있다고 가정을 한다.
- 위 답에서 첫 번째로 진행하는 회의를 지우고, Smin 을 추가한다.
- 지워진 회의는 Smin 보다 일찍 끝날 수 없다.
=> Smin 이 가장 먼저 끝나기 때문에, - 두번째 회의와 Smin 은 겹치지 않는다.
=> 지워진 회의와 Smin 은 겹칠 수 있어도,
=> 두번째 회의와 지워진 회의는 겹칠 수 없기 때문에 - 그래서, 새로 만든 목록도 최적해 중 하나가 된다.
=> 항상 Smin 을 포함하는 최적해는 존재한다.
관련 예제) 탐욕법 관련 예제 정리 필요...
[4. 최적 부분 구조]
항상 최적의 선택만을 해서 전체 문제의 최적해를 얻을 수 있음을 보여야 한다.
탐욕법의 정당성을 위해 증명해야 할 두번째 속성은 최적 부분 구조이다.
이 속성은 대개 매우 자명해서 따로 증명할 필요가 없는 경우가 대부분이다.
위 예제에서 첫번째 회의를 잘 선택하고 겹치는 회의를 모두 걸렀다면,
남은 회의 중에 당연히 최대한 많은 회의를 선택해야 한다.
[5. 동적계획법으로 풀이하기 여려운 경우]
예제) 각 팀이 n 명으로 구성되어 있고, 1대1 경기를 벌여 더 많은 승리를 가져가는 팀이 우승하는데,
상대방 팀 선수들의 출전 순서를 알고 있을 때,
어느 순서대로 선수들을 내보내야 승리 수를 최대화 할 수 있는가?
(레이팅이 같을 경우 우리 선수가 승리한다고 가정)
- 완전 탐색
=> 우리 팀 출전 방식 조합을 만드는 경우의 수는 n! 이므로, n 이 조금만 커져도 시간 초과 - 동적 계획법
=> n! 개의 답을 모두 생성하는 완전 탐색 알고리즘에 메모이제이션 적용 방법
=> 각 선수를 지금까지 순서에 추가했는지를 나타내는 bool 배열 만을 받는 부분문제
=> order(taken) = taken 에 각 선수 출전 여부가 주어질 때,
남은 선수들을 적절히 배치해서 얻을 수 있는 최대 승수
// 캐시를 어떻게 구성하지?
=> taken에 포함된 true 의 개수를 세면,
=> 이번에 선택할 선수가 상대팀의 몇번째 선수와 경기하게 되는지 알 수 있다.
=> 시간 복잡도 O(n*2^n) - 탐욕 알고리즘
=> W: 상대방 선수(A) 를 이길 수 있는 한국 선수가 있는 경우, 그 중 레이팅이 가장 낮은 선수를 상대와 경기 시킨다.
=> L: 상대방 선수(B) 가 한국팀의 모든 선수보다 레이팅이 높다면, 남은 선수 중 레이팅이 가장 낮은 선수과 경기 시킨다.
=== 탐욕적 선택 속성 증명
우리가 하는 선택을 포함하는 최적해가 존재함을 증명해야 한다.
W 인 경우와 L 인 경우로 나눠 탐욕적 선택이 옳다는 것을 증명하도록 한다.
L(질 수 밖에 없는) 경우를 고려
- 레이팅이 가장 낮은 선수 A 대신 B 를 내보내는 최적해가 있다고 가정한다.
- 최적해에서 이 두 선수의 순서를 바꿔본다.
=> ... B ... A ... => ... A ... B ... - 기존 최적해에서 A 와 대결했던 선수는 레이팅이 더 높은 B 를 상대해야 한다.
- 따라서 승수가 더 줄어들일은 없다
- 이 경기에 A 를 내보내는 최적해가 존재 함을 알 수 있다.
W(이길 수 있는 경우를 고려)
- 승리 할 수 있는 선수 중 레이팅이 가장 낮은 A 대신 레이팅이 더 높은 B 를 내보내는 최적해가 있다고 가정
- 최적해에서 이 두 선수의 순서를 바꿔본다.
=> ... B ... A ... => ... A ... B ... - 기존 최적해에서 A 와 대결했던 선수는 레이팅이 더 높은 B 를 상대해야 한다.
- 같은 전개로 이 순서 또한 최적해이다.
=== 최적 부분 구조 증명
첫번째 경기에 나갈 선수를 선택하고 나면, 남은 선수들을 배정하는 부분 문제를 얻는다.
이때 남은 경기에서도 최다 승을 얻어야, 전체에서 최다 승을 얻을 수 있다.
[6. 탐욕적 선택 속성 증명 패턴]
- 우리가 선택한 방법을 포함하지 않는 최적해의 존재를 가정한다.
- 적절히 조작해 우리가 선택한 방법을 포함하는 최적해를 만든다.
[7. 탐욕적 알고리즘 레시피]
- 문제의 답을 만드는 과정을 여러 조각으로 나눈다.
- 각 조각마다 어떤 우선순위로 선택을 내려야 할 지 결정한다.
- 아래 두 가지 속성을 증명한다.
A) 탐욕적 선택 속성
=> 항상 각 단계에서 우리가 선택한 답을 포함하는 최적해가 존재함을 증명한다.
=> 보통, 우리가 선택한 답과 다른 최적해가 존재함을 가정한다.
=> 선택한 답을 포함하는 최적해로 바꿀 수 있음을 보이도록 한다.
B) 최적 부분 구조
=> 대부분의 경우 자명하다.
'알고리즘 > 이론' 카테고리의 다른 글
04. 탐욕법 - 예제2 (0) | 2022.10.03 |
---|---|
04. 탐욕법 - 예제1 (0) | 2022.10.03 |
03. 동적계획법 - 예제4 (0) | 2022.10.02 |
03. 동적계획법 - 예제3 (0) | 2022.10.02 |
03. 동적 계획법 - 예제1 (0) | 2022.09.23 |