Ch 04. 그리디 알고리즘 (1)
그리디 알고리즘
개념
- 가능한 해 중, 
가장 좋은 해를 찾는 문제 
특징
- 전체 고려하지 않고 한 시점에서 최솟값/최댓값 데이터를 선택(= 근시안적)
 - 한 번 선택하면 절대 번복하지 않는다.
 
4.1 동전 거스름돈
그리디 알고리즘 아이디어
- 남은 액수 초과하지 않는 조건 하, 욕심내어 가장 큰 액면의 동전부터 취하는 것!
 - 최소 동전 수 찾기
 
구현
- Pseudocode
입력: 거스름돈 액수 W 
	CoinChange(W)
    	change = W;
        c500 = c100 = c50 = c10 = c1 = 0; //동전 개수 담는 변수
        
        while (change>=500) //500원으로 최대한 많이 거슬러 받기
        	{change -= 500; c500++;}
        while (change>=100)
        	{change -= 100; c100++;}
        while (change>=50)
        	{change -= 50; c50++;}
        while (change>=10)
        	{change -= 10; c10++;}
        while (change>=1)
        	{change -= 1; c1++;}
            
        return (c500+c100+c50+c10+c1);
과정
한계
- 거스름돈이 200원이고, 160원인 동전이 있다면?
- 160원 1개, 10원 4개
 - BUT! 100원 2개가 최적
 
 그리디알고리즘을 적용한 CoinChange 알고리즘이항상 최적 답을 제공하지 못한다.- 동적 계획 알고리즘: 어떤 경우에도 최적해 찾는 알고리즘
 
4.2 최소 신장 트리
4.2.1 신장트리, 최소 신장트리
개념
- 그래프
- 정점(V)과 간선(E) 집합으로 구성되는 비선형 자료구조
 
 신장트리- 그래프의 모든 정점 포함
 - 사이클 없음
 - V-1 개의 간선
 
최소신장트리(MST)- 신장트리 중, 
가중치의 합 최소 
- 신장트리 중, 
 
어떻게 찾을까?
- 그리디 알고리즘: 
Kruskal,Prim
 
4.2.2 Kruskal MST
개념
- 간선을 가중치 최솟값부터 오름차순 정렬
 - 최소 가중치부터 하나씩 꺼내어 신장트리 구성
 
구현
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
- Pseudocode
 
	KruskalMST(G)
    	L[e] = 가중치 오름차순으로 간선 정렬;
    	T = NULL; //출력 트리(최소신장트리) 초기화
        
        while(T의 간선 수 < n-1){
        	L에서 최소 가중치 간선 m 꺼내기;
            L에서 m 삭제;
            
            if (T에서 사이클 형성 시) //Union & Find
            	m 제외;
            else
            	T에 m 추가;
        }
        
        return T; //MST 리턴
과정(과제 구현)
시간복잡도
가중치 정렬: => 최소 힙정렬while Loop: 번Union & Find: => 경로 압축 시 Find 시간 복잡도
 
4.2.3 Prim MST
개념
- 임의의 점에서 시작
 - 인접 간선 중 최소 가중치 가진 간선 선택
 - 신장트리 구성될 때까지 반복
 
구현
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
최소신장트리 T
- Pseudocode 1(힙 사용하지 않는 경우)
 
	PrimMST1(G)
    /*D[v]는 T에 있는 점 u, v 연결 최소가중치 간선 갱신 배열*/
    	D[p] = 0; //임의의 시작 정점 
        
        for(p 외의 정점 v){ //D[v] 초기화
        	if ((p, v) 존재)
            	D[v] = w[p, v];
            else
            	D[v] = INTMAX;
        }
        T = {p};
        
        while(|T| < n){
        	//최소 가중치 간선 추가
        	if ((u in T) && (v not in T)) && min{D[v]}
            	T = T + {(u, v), v};
            
            // 가중치 재조정(갱신)
            for (w not in T){
            	if (w[u, w] < D[w])
                	D[w] = w[u, w];
            }
        }
        
        return T;
과정(과제 구현)
특징
- T 밖에 있는 점만을 추가하므로 사이클이 만들어지지 않는다.
 
시간복잡도
- 힙 자료구조 사용하지 않을 경우
 - 힙 자료구조(피보나치 힙) 사용할 경우
 
4.3 최단 경로 찾기
4.3.1 Dijkstra
개념
- 출발점에서 다른 도착점까지의 최단 경로를 찾는 문제
 - Prim vs. Dijkstra
Prim- 임의의 점에서 시작
 - 현재 상태 트리에서 가장 가까운 점 추가
 
Dijkstra- 출발점이 정해짐
 - 출발점으로부터 최단거리 정해지지 않은 점들 중, 출발점에서 가장 가까운 점 추가
 
 
구현
가중치 그래프 G = (V, E)
정점의 수 |V| = n
간선의 수 |E| = e
출발 정점 s
s부터 v까지의 최단거리 저장 배열 D
- Pseudocode
 
  ShortestPath(G, s){
  	  /*D[v] 무한대로 초기화*/
      D[s] = 0; 모든 D[v] = INTMAX;
      
      while(s부터의 최단거리 확정되지 않은 점 있을 때){
          확정 안 된 점 v에 대해 최소 D[v]인 점 v 선택;
          D[v] 확정;
          각 점 w, D[w] 최단거리 값으로 갱신;
      }
      
      return D;
  }
과정(과제 구현)
시간복잡도
- 
힙 자료구조 사용하지 않는 경우
- while Loop: 
n-1회- D[v] 최솟값인 점 v 찾기: 
O(n) - D[w] 갱신: 
O(n) 
 - D[v] 최솟값인 점 v 찾기: 
 
 - while Loop: 
 - 
힙(피보나치 힙) 사용하는 경우
 
4.4 부분 배낭 문제
개념
- n 개의 물건(무게/가치)
 - 최대의 가치를 갖도록 한정된 용량의 배낭에 넣을 물건들을 정하는 문제
 0-1 배낭 문제: 물건을 통째로 넣어야 한다.- 그리디로 해결 불가능
 - 동적계획 알고리즘, 백트래킹 기법, 분기한정 기법 활용
 
부분 배낭 문제: 물건을 쪼개서 담기 가능
단위 무게당 가치구하기- 단위 무게당 가치가 
높은 순으로 배낭에 넣기 - 통째로 넣을 수 없을 때, 
넣을 수 있을 만큼만 쪼개서담기 
구현
물건 개수: n
각 물건 무게: w
각 물건 가치: v
배낭 용량: C
배낭에 담은 물건 리스트: L
담은 물건 무게의 합: sum_w
담은 물건 가치의 합: sum_v
- Pseudocode
 
  FractionalKnapsack(n, w, v, C)
  	S = 각 물건의 단위 무게당 가치 계산;
    S = sorted(S, reverse = True); //내림차순 정렬
    
    L = NULL; sum_w = 0; sum_v = 0; //초기화
    
    x = S에서 단위 무게당 가치 가장 큰 물건;
    
    while(sum_w + w(x) <= C){
    // (무게 합 + x의 무게)가 배낭 총 용량보다 작거나 같을 때
    
    	L = L + {x};
        sum_w += w(x);
        sum_v += v(x);
        
        S = S - {x};
        x = S에서 단위 무게당 가치 가장 큰 물건;
    
    }
    
    if((C - sum_w) > 0){ //배낭에 쪼개서 담을 여유 있으면
    	L = L + {x};
    	sum_w += {(C-sum_w)만큼의 w(x)};
        sum_v += {(C-sum_v)만큼의 w(v)};
    }
    
    return L, v; //담긴 물건 리스트, 가치의 합
시간복잡도
- 단위 무게당 가치 계산: 
O(n) - 내림차순 정렬: 
O(nlogn) - while Loop: 최대 
n번- 담는 작업: 
O(1) 
 - 담는 작업: 
 - 나머지 쪼개서 담기: 
O(1) 
Author And Source
이 문제에 관하여(Ch 04. 그리디 알고리즘 (1)), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@gamza363/Ch-04.-그리디-알고리즘-1저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
                                
                                
                                
                                
                                
                                우수한 개발자 콘텐츠 발견에 전념
                                (Collection and Share based on the CC Protocol.)