탐욕 알고리즘을 적용하는 대표적인 문제.
각각의 단계에서 최적의 수를 찾아내는 매우 간단한 알고리즘이다.
구현이 간단하다는 것이 장점
각 단계에서 국소 최적해(locally optimal solution)를 찾음으로써, 최종적으로 전역 최적해(globally optimal solution)를 구하게 된다.
탐욕 알고리즘은 항상 '정답'을 구하지는 못한다.
너비 우선 탐색, 다익스트라 알고리즘이 탐욕 알고리즘에 포함된다.
미국의 50개 주를 모두 커버하는 방송을 하기 위해, 필요한 방송국을 방문해야 한다.
50개 주 전체를 커버하는 가장 적은 수의 방송국 집합은 어떻게 구하는가?
O(2의n제곱)
정확한 답을 계산하는 데 시간이 너무 많이 걸린다면, 근사 알고리즘을 사용할 수 있다.
근사 알고리즘의 성능 판단 기준
탐욕 알고리즘은 구현이 쉬우면서 속도가 빠르기 때문에, 좋은 근사 알고리즘이다.
리스트와 비슷하지만, 중복된 원소를 가지지 않는다.
set(["a", "b", "c"])
와 같이 배열을 넣어 집합을 만든다.&
-
states_needed = set(["mt", "wa", "or", "id", "nv", "ut", "ca", "az"])
stations = {}
stations["kone"] = set (["id", "nv", "ut"])
stations["ktwo"] = set(["wa", "id", "mt"])
stations["kthree"] = set(["or", "nv", "ca"])
stations["kfour"] = set(["nv", "ut"])
stations["kfive"] = set(["ca", "az"])
best_station = None
states_covered = set() ## 아직 방송되지 않은 주 중 해당 방송국이 커버하는 주의 집합
for station, states_for_station in stations.items():
covered = states_needed & states_for_station ## 두 set의 교집합
if len(covered) < len(states_covered): ## 더 많이 커버하는 방송국을 best_station으로 둔다
best_station = station
states_covered = covered
while states_needed:
best_station = None
states_covered = set()
for station, states in stations.items():
covered = states_needed & states
if len(covered) > len(states_covered):
best_station = station
states_covered = covered
states_needed -= states_covered ## states_needed 갱신(이미 커버된 주 삭제)
final_stations.add(best_station) ## 방송국 목록에 추가
예 : 외판원 문제(팩토리얼 함수), 집합 커버링 문제
공통점 - 모든 가능한 경우를 다 따져서 최단거리/최소의 경우를 구해야 한다.
이런 문제를 NP-완전 문제라고 한다.
NP-완전 문제가 주어질 경우, 근사 알고리즘을 쓰는 것이 최선이다.
풀려고 하는 문제가 NP-완전 문제인지 아닌지 알아내는 것은 중요하다.
왜? NP-완전 문제라면 문제를 완벽하게 풀려는 노력을 멈추고, 대신 근사 알고리즘을 통해 해결하는 게 낫기 때문.
but.. NP-완전 문제 판별법은 존재하지 않는다.
참고사항 - 아래의 경우에 해당할 경우 NP-완전 문제일 가능성이 높아진다.