N = 1260일 때의 예시를 살펴보자.
가장 큰 화폐 단위부터 돈을 거슬러 주는 것이 최적의 해를 보장하는 이유가 무엇일까?
그것은 가지고 있는 동전 중에서 큰 단위가 항상 작은 단위의 배수이므로, 작은 단위의 동전들을 조합하여 다른 해가 나올 수 없기 때문이다.
만약, 800원을 거슬러 줘야 하는데 화폐 단위가 500원, 400원, 100원이라면?
그리디 알고리즘에 따르면 500원 1개, 100원 3개로 총 4개가 나오는데, 사실 최적의 해는 400원짜리 2개이다. 다시 말해, 큰 단위가 작은 단위의 배수가 아니라면 그리디 알고리즘으로 최적의 해를 보장하지 못한다.
이처럼 그리디 알고리즘은 문제 풀이를 위한 최소한의 아이디어를 떠올리고 그것이 정당한지 검토하는 것이 중요하다.
n = 1260
count = 0
# 큰 단위의 화폐부터 차례로 확인하기
array = [500, 100, 50, 10]
for coin in array:
count += n // coin # 해당 화폐로 거슬러 줄 수 있는 동전의 개수 세기
n %= coin
print(count)
https://www.acmicpc.net/problem/11047
n 종류의 동전으로 k원을 만드는 데 필요한 동전 개수의 최솟값을 구하는 문제이다. 위에서 예시로 봤던 거스름돈 문제랑 동일하다.
1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수
위 설명에 따르면 큰 단위가 항상 작은 단위의 배수이므로, 그리디 알고리즘으로 최적해를 구할 수 있다. 하지만, 동전의 단위가 서로 배수 관계가 아닐 때는 동전 단위를 1부터 k까지 늘려가면서 DP로 최적해를 구해야 한다.
#include<iostream>
#include<vector>
using namespace std;
int main() {
int n, k;
cin >> n >> k;
vector<int> v;
for (int i = 0; i < n; i++) {
int coin;
cin >> coin;
v.push_back(coin); // 오름차순으로 입력
}
int cnt = 0; // 필요한 최소 동전의 개수
// 큰 화폐 단위부터 그리디하게 (탐욕적으로) 선택한다.
for (int i = n - 1; i >= 0; i--) {
cnt += k / v[i];
k %= v[i];
}
cout << cnt << "\n";
return 0;
}