프로그래밍 언어/자료구조 & 알고리즘
알고리즘 설계 기법 - Greedy 알고리즘/욕심쟁이 기법
by Hyeon_
2021. 11. 29.
알고리즘 설계기법
욕심쟁이 기법 (Greedy method)
- 최적 해답을 구성할 수 있는 집합을 만들기 위해 필요한 원소를 각 단계마다 하나씩 선택해 나가는 방법
- 선택을 하는 매 순간마다 현재 상태에서 가장 좋아 보이는 원소를 선택하는 전략
- 최적의 해를 찾는 전형적인 해결 방법
- 즉, 각 순간에 지역적으로 가장 좋아 보이는 선택이 보여서 전체적으로 가장 좋은 최종의 답에 이르는 문제가 많기 때문에 전략이라고 할 수 있음
- 이 기법은 모든 최적화 문제를 해결할 수는 없으나, 많은 경우의 문제에 쉽게 적용할 수 있는 기법 중 하나
욕심쟁이 기법 적용 예
- 배낭 채우기 문제
- 거스름돈 문제
- 최단 경로 문제(Dijkstra의 최단 경로 Algorithm)
- 최소 비용 신장 트리
- Prim(프림)의 알고리즘
- Krusckal(크루스컬) 알고리즘
연습문제
욕심쟁이 기법 적용 예 - 배낭 문제(knapsack problem)
- n개의 물건과 이 물건을 담을 수 있는 배낭이 있을 때 어떤 물건들을 선택해서 배낭에 넣으면 배낭 안에 있는 물건들의 총 가격이 가장 크게 되는가
- 제약조건
- 배낭에 넣을 수 있는 최대 무게는 제한한다
- 배낭 안에 넣은 물건들의 총 무게는 이 제한 무게를 넘지 않아야 한다
- 문제
- 배낭의 제한 무게는 15Kg
- 각 무게와 가격은 다음과 같음(분할 가능)
- 1번: 60원, 4Kg
- 2번: 45원, 9Kg
- 3번: 21원, 7Kg
- 4번: 12원, 3Kg
- 배낭에 최대로 담을 수 있는 물건들과 총 가격은 얼마인가?
욕심쟁이 기법에 의해 하나씩 물건을 선택할 때 고려할 전략
60원 4Kg + 45원 9Kg + 21/7 * 2Kg = 111원
12원 3Kg + 60원 4Kg + 21원 7Kg + 45원/9 1Kg = 98원
- 각 물건의 단위 무게당 가격을 계산한 후 이 값이 더 큰 순서로 물건을 선택하는 전략
- 무게의 증가에 비해 가격이 최대한 많이 증가하는 전략이 최적의 해답
15원 * 4Kg + 5원 * 9Kg + 4원 * 2Kg = 113원
욕심쟁이 기법 적용 예 - 거스름돈 문제
- 동전의 개수가 최소가 되도록 거스름돈을 주는 문제
- 거스름돈: 890원
- 먼저 가치가 가장 높은 동전부터 거스름돈을 초과되지 않도록 내줌
- 500원 동전 1개
- 100원 동전 3개
- 50원 동전 1개
- 10원 동전 4개
- 이 과정을 가치가 높은 동전부터 내림차순으로 총액이 정확히 거스름돈이 될 때까지 계속 수행
- 문제
- 입력한 금액만큼 큰 단위 순으로 지불
- 5,000원 지폐
- 1,000원 지폐
- 500원 동전
- 100원 동전
- 50원 동전
- 금액 입력: 18793
- 5000원: 3
- 1000원: 3
- 500원: 1
- 100원: 4
- 50원: 1
- 10원: 2
- 나머지: 3
import java.util.Scanner;
public class Greedy_Coin {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
// 최소단위 10, 최대단위 5000
int price = 0;
System.out.print("총 금액 입력: ");
price = scan.nextInt();
int[] arr = {5000,1000,500,100,50,10};
for(int i=0; i<arr.length; i++) {
//금액을 대입해서 자동계산
if(price/arr[i] > 0) {
System.out.println(arr[i]+"원: "+price/arr[i]+"개 ");
price%=arr[i];
}
}
System.out.println("잔돈: "+price+"원");
}
}
Dijkstra(다익스트라)의 최단 경로 알고리즘
- 하나의 출발점에서
모든 종착점
의로의 최단경로
를 찾는 문제
- 네트워크에서 하나의 시작 정점으로부터 모든 다른 정점까지의 최단 경로를 찾는 알고리즘
- 집합 S
- 시작 정점 v로부터의 최단 경로가 이미 발견된 정점들의 집합
- distance 배열
- 최단 경로를 알려진 정점만을 통하여 각 정점까지 가는 최단 경로의 길이
- 매 단계에서 distance의 값이 가장 적은(비용이 적은: 최적) 정점을 S에 추가
최소 비용 신장 트리(MST : Minimum Spanning Tree)
- 트리를 구성하는 간선들의 가중치를 합한 것이 최소가 되는 신장 트리
- 네트워크에 있는 모든 정점들을 가장 적은 수의 간선과 비용으로 연결하는 신장 트리
- MST의 응용
- 도로 건설
- 도시들을 모두 연결하면서 도로의 길이가 최소가 되도록 하는 문제
- 전기 회로
- 단자들을 모두 연결하면서 전선의 길이가 가장 최소가 되도록 하는 문제
- 통신
- 전화선의 길이가 최소가 되도록 전화 케이블 망을 구성하는 문제
- 배관
- 파이프를 모두 연결하면서 파이프의 총 길이가 최소가 되도록 연결하는 문제
- 최소 비용 신장 트리 알고리즘
- 프림(Prim)의 알고리즘
- 크루스컬(Kruskal)의 알고리즘
프림(Prim)의 알고리즘
- 한 번에 하나의 간선을 선택하여 최소 비용 신장 트리 T에 추가
- 구축 전 과정을 통해 하나의 트리만을 계속 확장
- 이 과정은 트리가 n-1개의 간선을 가질 때까지 계속
크루스컬(Kruskal) 알고리즘
- 한 번에 하나의 간선을 선택하여 최소 비용 신장 트리 T에 추가
- 비용이 가장 적은 간선을 선정하되, 이미 T에 포함된 간선들과 사이클을 형성하지 않는 간선만을 추가
- 비용이 같은 간선들의 임의의 순서로 하나씩 추가