Algorithm/백준

*[백준][11047] 동전 0

1일1코딩 2021. 4. 13. 00:11

www.acmicpc.net/problem/11047

 

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;
}

 

결과