Baekjoon Review
[Gold 5] 2294 동전 2
hanseongbugi
2024. 2. 6. 17:39
https://www.acmicpc.net/problem/2294
2294번: 동전 2
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다. 가치가 같은 동전이 여러 번 주어
www.acmicpc.net
이 문제는 동전 1과 유사한 문제다.
단, 동전 1과 다르게 동전 합의 최소 개수를 구하는 문제다.
동전 합의 최소 개수를 구하기 위해선 그리드 알고리즘이나 DP를 사용하면 된다.
이 문제인 경우 동전의 가치가 배수 관계가 아니기 때문에 DP를 사용해야만 한다.
DP 식은 아래와 같다.
동전의 가치인 arr[i-1]에 따라 dp[j]를 구한다. 이때 arr[i-1]에 따라 dp[j]를 더 작게 구할 수 있다면 dp를 갱신한다.
위 식을 예제 표로 바꾸면 다음과 같다.
dp를 0으로 초기화 한 후 동전 1에 대해 경우의 수를 구한다.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
동전 5에 대해 경우의 수를 구한다. 1~4를 구할 수 있는 경우는 없기에 5번째 부터 구한다.
0 1 2 3 4 1 2 3 4 5 2 3 4 5 6 3
동전 12에 대해 경우의 수를 구한다.
0 1 2 3 4 1 2 3 4 5 2 3 1 2 3 3
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int N, K;
int arr[101];
int dp[10001] = { 0, };
int main() {
ios_base::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin >> N >> K;
for (int i = 0; i < N; i++) cin >> arr[i];
for (int i = 1; i <= K; i++) dp[i] = 10001;
for (int i = 1; i <= N; i++) {
for (int j = arr[i-1]; j <= K; j++) {
dp[j] = min(dp[j], dp[j - arr[i-1]] + 1);
}
}
if (dp[K] == 10001) cout << -1 << '\n';
else cout << dp[K] << '\n';
}