*[백준][11047] 동전 0
11047번: 동전 0
첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000) 둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)
www.acmicpc.net
문제
준규가 가지고 있는 동전은 총 N종류이고, 각각의 동전을 매우 많이 가지고 있다.
동전을 적절히 사용해서 그 가치의 합을 K로 만들려고 한다. 이때 필요한 동전 개수의 최솟값을 구하는 프로그램을 작성하시오.
입력
첫째 줄에 N과 K가 주어진다. (1 ≤ N ≤ 10, 1 ≤ K ≤ 100,000,000)
둘째 줄부터 N개의 줄에 동전의 가치 Ai가 오름차순으로 주어진다. (1 ≤ Ai ≤ 1,000,000, A1 = 1, i ≥ 2인 경우에 Ai는 Ai-1의 배수)
출력
첫째 줄에 K원을 만드는데 필요한 동전 개수의 최솟값을 출력한다.
해결 방법 (재귀 + 그리디)
동전의 액수가 큰 금액이 많을 수록 최소 동전 갯수를 구 할 수 있다고 생각하였다.
따라서 가장 큰 동전부터 해당 동전을 최대한 많은 갯수를 가지도록 재귀 함수를 이용하였다.
하지만 최초로 0값에 도달하는 루틴이 최적의 루틴임을 간과하여, 시간초과가 발생하였다.
큰 동전의 최대 갯수부터 작은 동전까지 도달하기 때문에, 최초로 0값에 수렴하는 방법이 최소 갯수가 될 수 있다는 조건을 추가하여 해결 할 수 있었다.
solution함수의 if(answer != MAX_ANSWER || cur == 0) 조건이 이에 해당된다.
소스코드
#include <stdio.h>
#include <vector>
#include <algorithm>
#define MAX_ANSWER 987654321
using namespace std;
vector<int> moneyType;
int answer = MAX_ANSWER;
void solution(int cur, int depth, int sum)
{
if (answer != MAX_ANSWER || cur < 0) return;
if (depth < 0 || cur == 0) {
if (cur == 0 && sum < answer) {
answer = sum;
}
return;
}
int curMoneyType = moneyType[depth];
if (cur >= curMoneyType) {
int maxCount = cur / curMoneyType;
for (int i = maxCount; i >= 0; i--) {
solution(cur - (curMoneyType * i), depth - 1, sum + i);
}
}
else {
solution(cur, depth - 1, sum);
}
}
int main()
{
int N, K;
scanf("%d %d", &N, &K);
for (int i = 0; i < N; i++) {
int n;
scanf("%d", &n);
moneyType.push_back(n);
}
solution(K, N - 1, 0);
printf("%d\n", answer);
return 0;
}
결과