|
| 1 | +### 개념 |
| 2 | + |
| 3 | +**"현재 상황에서 지금 당장 좋은 것만 고르는 방법"** |
| 4 | + |
| 5 | +- **정렬, 최단 경로** 문제에서 기본 지식으로 사용됨 |
| 6 | +- **Dijkstra Algorithm** 또한 greedy algorithm으로 분류됨 |
| 7 | + |
| 8 | +### 예제 |
| 9 | + |
| 10 | +- 거스름돈 (거슬러 줘야 할 최소 동전 개수 구하기) |
| 11 | + - 그리디 알고리즘이 정당한 이유 : 가지고 있는 동전 중에서 큰 단위가 항상 작은 단위의 배수이므로 작은 단위의 동전들을 종합해 다른 해가 나올 수 없기 때문 |
| 12 | + - ex) 500원, 100원, 50원 |
| 13 | + - (화폐의 단위가 무작위로 주어진 문제는 다이나믹 프로그래밍으로 해결할 수 있다) |
| 14 | + |
| 15 | +### 코드 : **Dijkstra Algorithm** |
| 16 | + |
| 17 | +- 그래프에서 한 정점에서 다른 모든 정점으로 가는 최단 경로를 찾는 알고리즘 |
| 18 | +- 이 알고리즘은 주로 가중치가 있는 그래프에서 사용됨 (가중치≠음수) |
| 19 | + |
| 20 | +작동 방식 |
| 21 | + |
| 22 | +1. 시작 정점의 최단 경로 비용을 0으로 설정하고, 다른 모든 정점의 비용은 무한대로 설정합니다. |
| 23 | +2. 모든 정점이 처리될 때까지 다음을 반복합니다: |
| 24 | + - 처리되지 않은 정점 중에서 최단 경로 비용이 가장 작은 정점을 선택합니다. |
| 25 | + - 이 정점을 통해 갈 수 있는 인접한 정점들의 경로 비용을 갱신합니다. |
| 26 | + |
| 27 | +```python |
| 28 | +import heapq |
| 29 | + |
| 30 | +def dijkstra(graph, start): |
| 31 | + # 그래프의 각 정점에 대한 최단 경로 비용을 무한대로 초기화 |
| 32 | + distances = {vertex: float('infinity') for vertex in graph} |
| 33 | + distances[start] = 0 # 시작 정점의 비용은 0으로 설정 |
| 34 | + priority_queue = [(0, start)] # 우선순위 큐, (비용, 정점) 형태로 저장 |
| 35 | + |
| 36 | + while priority_queue: |
| 37 | + current_distance, current_vertex = heapq.heappop(priority_queue) |
| 38 | + |
| 39 | + # 더 작은 비용의 경로가 있을 경우 무시 |
| 40 | + if current_distance > distances[current_vertex]: |
| 41 | + continue |
| 42 | + |
| 43 | + # 인접한 정점들을 검사하며 거리 업데이트 |
| 44 | + for neighbor, weight in graph[current_vertex].items(): |
| 45 | + distance = current_distance + weight |
| 46 | + |
| 47 | + # 현재 저장된 거리보다 작은 거리를 찾았다면 업데이트하고 큐에 추가 |
| 48 | + if distance < distances[neighbor]: |
| 49 | + distances[neighbor] = distance |
| 50 | + heapq.heappush(priority_queue, (distance, neighbor)) |
| 51 | + |
| 52 | + return distances |
| 53 | + |
| 54 | +# 그래프 예시 |
| 55 | +graph = { |
| 56 | + 'A': {'B': 1, 'C': 4}, |
| 57 | + 'B': {'A': 1, 'C': 2, 'D': 5}, |
| 58 | + 'C': {'A': 4, 'B': 2, 'D': 1}, |
| 59 | + 'D': {'B': 5, 'C': 1} |
| 60 | +} |
| 61 | + |
| 62 | +# 알고리즘 실행과 결과 출력 |
| 63 | +start_vertex = 'A' |
| 64 | +distances = dijkstra(graph, start_vertex) |
| 65 | +print(f"Starting from vertex '{start_vertex}':") |
| 66 | +for vertex in distances: |
| 67 | + print(f"Distance to vertex {vertex} is {distances[vertex]}") |
| 68 | + |
| 69 | +# Starting from vertex 'A': |
| 70 | +# Distance to vertex A is 0 |
| 71 | +# Distance to vertex B is 1 |
| 72 | +# Distance to vertex C is 3 |
| 73 | +# Distance to vertex D is 4 |
| 74 | +``` |
| 75 | + |
| 76 | +### 팁 |
| 77 | + |
| 78 | +- 문제의 유형이 다양해서 암기로는 풀기 힘들다 → 많은 유형의 문제를 접해보고 풀어보는 훈련 필요 |
| 79 | + - 문제 유형을 파악하기 어렵다면 그리디 알고리즘을 의심하고, 문제를 해결할 수 있는 탐욕적인 해결법이 존재하는지 고민해보자. |
| 80 | + - 그리디 알고리즘으로 해결 방법을 찾을 수 없다면, 다이나믹 프로그래밍이나 그래프 알고리즘 등으로 문제를 해결할 수 있는지를 재차 고민 |
| 81 | +- 그리디 알고리즘은 기준에 따라 좋은 것을 선택하는 알고리즘이므로 문제에서 ‘가장 큰 순서대로’, ‘가장 작은 순서대로’와 같은 기준을 알게 모르게 제시해준다 |
| 82 | + - 대체로 이 ‘기준’은 정렬 알고리즘을 사용했을 때 만족 시킬 수 있으므로 그리디 알고리즘 문제는 **자주 정렬 알고리즘과 짝을 이뤄 출제된다** |
| 83 | +- "문제풀이를 위한 최소한의 아이디어를 떠올리고, 이것이 정당한지 검토하기" |
| 84 | + |
| 85 | +참고자료 : |
| 86 | + |
| 87 | +https://yozm.wishket.com/magazine/detail/2478/?utm_source=stibee&utm_medium=email&utm_campaign=newsletter_yozm&utm_content=contents |
0 commit comments