이번에 해외여행을 일본으로 다녀오느라 포스팅이 불규칙적이었다.
일본여행 중 굉장히 동전을 많이 가지고 있게 되었는데, 귀국할때 최대한 동전을 적게 들고오기 위해 계산을 했던 기억이 난다. 그때의 기억을 떠올려보며 글을 써보려 한다.
Baekjoon / Problem No. 11047 (동전 0)
Problem
준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다.
동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오.
Input
첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000)
둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)
Output
첫째 줄에 K원을 만드는데 필요한 동전 개수의 최솟값을 출력한다.
Solution
동전의 개수를 최소로 하면서 일정 금액을 만드는 문제이다.
돈의 특징으로 100원 5개가 500원 1개로 대체될 수 있다라는 점을 생각해보자.
동전의 개수를 최소화 해야하기 때문에 당연히 더 높은 금액권으로 지불할 수 있다면 그렇게 하는 편이 유리하다.
이런식으로 고액권 부터 차례로 (위에서 서술한)유리한 상황을 순간 순간 이어나갈 수 있다면?
결과적으로 유리한 상황이 계속 유지될 것이므로, 최적의 답을 찾을 수 있을 것이다.
바로 이것이 그리디 알고리즘을 (쉽게) 설명한 것이라고 생각하면 된다.
그리디 알고리즘(Greedy Algorithm)은 '탐욕 알고리즘'이라는 뜻으로, 그 순간 순간 최적이라 생각하는 방향을 계속 따라가면 최선의 결과가 나올것이라 생각하는 알고리즘이다.
이 문제의 경우 심지어 더 편하게 동전의 가치를 순서대로 제시하고 있으므로, K를 고액권부터 차례로 나눠가면서 나눠진 수만큼 카운팅하여 출력만 하면 될 것이다.
Code
#include <cstdio>
#include <vector>
using namespace std;
int main()
{
int N, K;
int count = 0;
vector<int> cost;
scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++)
{
int c;
scanf("%d", &c);
cost.push_back(c);
}
for (int j = N - 1; j >= 0; j--)
{
count += (K / cost[j]); // 동전을 사용한 횟수
K = K % cost[j];
}
printf("%d", count);
return 0;
}
Review
간단한 일종의 그리디 알고리즘을 통해 문제를 해결해 보았다.
그리디 알고리즘은 위에서 설명하였듯이, 항상 최선의 선택을 한다면, 결국 최선의 결과가 나올 것이라고 본다.
어찌보면 역설적이게도 그리디 알고리즘 그 자체도 역시 최선이 아니다.
그 순간 순간에 최선의 선택을 한다고 해도 그것이 최선의 결과로 이어질지는 미지수이기 때문이다.
우리도 그렇다. 매 순간 순간 행복하기위해 이것저것 선택하고 결정해도 그것이 진정 그 끝에서 최선의 길인지 사실은 누구도 모른다.
최선의 결과는 어디에서 보나 최선이라고 볼 수 없다.
그것도 엄청난 수의 사람들이 살아가는 이 세상이 돌아가는 알고리즘(이 있을지는 모르겠다.)속에서는
무엇이 최선의 선택인지조차 알 수 없다.
우리는 주로 위인들의 시련과 그것을 멋지게 극복해내는 스토리에 열광하곤 한다.
항상 완벽할 필요는 없다. 그것이 진정한 완벽인지는 그 끝에 가서야 알수 있으니까.
사설이 길었다.
여행과 개인적인 사정으로 며칠동안 오늘의 코드를 조금 쉬게 되었다. 더 나은 포스트를 위한 투자로 봐준다면 감사하겠다.
'오늘의 코드' 카테고리의 다른 글
| 오늘의 코드. 15일차 (백준/11170번 0의 개수) (0) | 2024.02.23 |
|---|---|
| 오늘의 코드. 13일차 (백준/12789번 도키도키 간식드리미) (0) | 2024.02.16 |
| 오늘의 코드. 12일차 (백준/11758번 CCW) (2) | 2024.02.15 |
| 오늘의 코드. 11일차 (백준/2563번 색종이) (2) | 2024.02.14 |
| 오늘의 코드. 10일차 (백준/27960번 사격 내기) (2) | 2024.02.13 |