[C#, Algorithm] 그라디(탐욕, 욕심쟁이) 알고리즘

2025. 4. 10. 18:16·Unity,C#/알고리즘
728x90

■ 그라디(Greedy) 알고리즘

[그라디 알고리즘]

그라디(탐욕, 욕심쟁이) 알고리즘은 매 단계에서 “가장 좋아 보이는 선택”을 하는 알고리즘이다. 이 선택이 전체적으로도 최적일 거라는 가정 하에 작동한다.

  • 항상 최적의 값을 계산하는것을 보장하진 않는다. 다만 최적에 “근사한 값”을 목표로 한다.

예시로 위 상황에서 항상 최적의 값(가장 짧은 KM)을 구하면 서울(40)→이천(80)→대구(30)의 순으로 총 150KM가 나온다. 하지만 서울→이천→대전→부산으로 가는 경로는 총 145KM이기 때문에 최적에 근사한 값을 내는 것을 확인할 수 있다.

 

예시) “손님에게 거스름돈을 줄 때 가장 적은 개수의 동전으로 거스름돈을 주려고 한다.”

사용 가능한 동전의 종류는 [500원,100원,50원,10원]일 때, 거슬러 줘야 할 동전의 최소 개수를 구하는 프로그램을 작성해 보자.

internal class Greedy
{
    public Dictionary<int, int> CalculateChange(int[] coin, int change)
    {
        // 1. 문제를 정렬 가능한 구조로 파악하기
        // - 여기서는 거슬러 줄 동전을 내림차순으로 정렬
        Array.Sort(coin, (a, b) => b.CompareTo(a));
        
        var result = new Dictionary<int, int>();

        // 2. 탐욕적인 기준 정의
        // - 여기서는 가장 큰 동전부터 선택
        for(var i = 0; i < coin.Length; i++) 
        {
            var cnt = change / coin[i];
            change %= coin[i];

            result.Add(coin[i], cnt);
        }

        // 3. 그 선택이 전체 최적을 보장하는지 검증
        // - 여기서는 남은 금액이 0원이면 최적해를 구함.
        if(change <= 0)
        {
            return result;
        }

        // 4. 최적해를 구하지 못하면 실패(-1, 남은 돈)를 반환
        result.Add(-1, change);
        return result;
    }
}

 

그라디 알고리즘을 적용할 때 따라야 할 표준적인 절차가 있다.

  1. 문제를 정렬 가능한 구조로 파악한다.
    • 문제를 작은 부분 문제들로 나눌 수 있는지 확인하고, 각 부분 문제의 최적해를 조합했을 때 전체 문제의 최적해가 되는지 살펴본다.
    • 예를 들어, 거스름돈 문제에서는 동전 단위를 내림차순 정렬하여 큰 단위의 동전을 먼저 고려할 수 있다.
  2. 탐욕적인 기준(Greedy 기준)을 정의한다.
    • 매 순간 어떤 선택이 가장 "좋은 선택"인지 판단할 기준을 세운다.
    • 예: 비용이 작거나, 가치가 크거나, 가장 빠르게 끝나는 것 등.
  3. 그 선택이 전체 죄적을 보장하는지 검증한다.
    • 그라디 알고리즘이 항상 최적해를 보장하는지 수학적, 혹은 논리적으로 확인해야 한다.
    • 최적 부분구조와 탐욕 선택 속성을 모두 만족해야 한다.
Greedy Choice Property(최적 부분 구조)  문제를 부분 문제로 나눴을 때, 그 부문 문제의 최적해를 합치면 전체 문제의 최적해가 된다는 성질.
Optimal Substructure(탐욕 선택 속성) 전체 문제의 최적해가, 부분 문제의 최적해로부터 구성될 수 있는가?

 

위 문제에선 “가장 큰 동전을 먼저 선택한다”라는 조건으로 각 순간마다 가장 많은 금액을 줄 수 있도록(최선) 되어있다.

또한 620원을 500 + 120원으로 나눴다면, 120원에 대해서도 같은 방법(100→10)으로 거슬러 줄 수 있기 때문에 탐욕 선택 속성도 만족한다.

  • 이 두 조건을 만족하므로, 그라디가 항상 죄적해를 보장한다.

 

▶ 반례

그런데 위 경우 항상 보장되는 것은 아니다. 동전 단위가 애매하면 반례가 생긴다. 동전 단위가 [500,400,100]이라면,

  • 800원을 거슬러 줄 때 :
    • 그라디 : 500 + 100 + 100 + 100 = 동전 4개
    • 최적해 : 400 + 400 = 동전 2개 ← 최적!

반례가 존재한다는 건, 그라디 알고리즘을 쓰면 항상 최적해를 구할 수 없기 때문에 적용하면 안 된다.

728x90

'Unity,C# > 알고리즘' 카테고리의 다른 글

[정렬 알고리즘, C#] 버블 정렬(Bubble Sort)  (1) 2025.06.17
[C#, Unity, 최단경로(PathFinding)] TileMap A* 알고리즘  (0) 2025.04.10
[C#, Unity, 최단경로(PathFinding)] TileMap 다익스트라(Dijkstra) 알고리즘  (0) 2025.04.10
[C#, Algorithm] Dynamic Programming(동적 계획법)  (0) 2025.04.10
[C#, Unity, 최단경로(PathFinding)] TileMap 너비우선탐색(BFS) 알고리즘  (1) 2025.04.07
'Unity,C#/알고리즘' 카테고리의 다른 글
  • [C#, Unity, 최단경로(PathFinding)] TileMap A* 알고리즘
  • [C#, Unity, 최단경로(PathFinding)] TileMap 다익스트라(Dijkstra) 알고리즘
  • [C#, Algorithm] Dynamic Programming(동적 계획법)
  • [C#, Unity, 최단경로(PathFinding)] TileMap 너비우선탐색(BFS) 알고리즘
브라더스톤
브라더스톤
유티니, C#과 관련한 여러 정보를 끄적여둔 블로그입니다. Email : dkavmdk98@gmail.com
  • 브라더스톤
    젊은 프로그래머의 슬픔
    브라더스톤
  • 전체
    오늘
    어제
    • 개발 노트 (26) N
      • Unity,C# (26) N
        • Unity 정보 (5) N
        • 알고리즘 (10)
        • 자료구조 (2)
        • 절차적생성(PCG) (9)
      • C++ (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    CustomWindow
    PerlinNoise
    절차적 던전 생성
    unity
    알고리즘
    이진공간분할
    이진공간분할법
    C#
    자료구조
    최단경로찾기
    커스텀 윈도우
    커스텀 인스펙터
    binary space partitioning
    BSP
    정렬알고리즘
    CustomEditorWindow
    절차적지형생성
    pcg
    Custom Inspector
    절차적던전생성
  • 최근 댓글

  • 최근 글

  • 250x250
  • hELLO· Designed By정상우.v4.10.3
브라더스톤
[C#, Algorithm] 그라디(탐욕, 욕심쟁이) 알고리즘
상단으로

티스토리툴바