2294번 동전 2
문제
n가지 종류의 동전이 있다. 이 동전들을 적당히 사용해서, 그 가치의 합이 k원이 되도록 하고 싶다. 그러면서 동전의 개수가 최소가 되도록 하려고 한다. 각각의 동전은 몇 개라도 사용할 수 있다.
사용한 동전의 구성이 같은데, 순서만 다른 것은 같은 경우이다.
입력
첫째 줄에 n, k가 주어진다. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) 다음 n개의 줄에는 각각의 동전의 가치가 주어진다. 동전의 가치는 100,000보다 작거나 같은 자연수이다. 가치가 같은 동전이 여러 번 주어질 수도 있다.
출력
첫째 줄에 사용한 동전의 최소 개수를 출력한다. 불가능한 경우에는 -1을 출력한다.
예제 입력
3 15
1
5
12
예제 출력
3
해결방법
동전 교환 알고리즘
을 적용한 DP 문제이다
⭐️ 솔루션 ⭐️
C(i) : i 번째 동전의 가치
D(i, k) : i 번째까지의 동전을 사용하여 k원을 만들 때, 동전의 최소 개수
- 첫번째 동전만 사용했을때, 1~k 원까지 만들 수 있는 최소 동전 개수를 설정한다
- 두번째 동전을 추가하여, 1~k 원까지 만들 수 있는 최소 동전 개수를 갱신한다
- 1 ~ n 번 동전을 사용했을 때, 1~k 원까지 만들 수 있는 최소 동전 개수를 갱신한다
점화식은 아래와 같다
D(i,k)
{
[C(i) > k] D(i-1,k)
[C(i) = k] 1
[C(i) ≤ k] min(D(i-1,k),D(i,k-C(i)) + D(C(i)))
}
소스코드
#include <iostream>
#include <algorithm>
#define INF 987654321
using namespace std;
int n,k;
int c[101];
int d[10001];
void dp(){
d[0] = 1;
for(int i=1; i<=n; i++){
for(int j=1; j<=k; j++){
if(c[i] == j){
d[j] = 1;
}else if(c[i] <= j){
d[j] = min(d[j],(d[c[i]] + d[j-c[i]]));
}
}
}
if(d[k] == INF)
cout << -1 << "\n";
else
cout << d[k] << "\n";
}
int main(int argc, const char * argv[]) {
// cin,cout 속도향상
ios_base::sync_with_stdio(false);
cin.tie(NULL); cout.tie(NULL);
// 입력
cin >> n >> k;
for(int i=1; i<=n; i++){
cin >> c[i];
}
// 초기화
for(int i=1; i<=k; i++){
d[i] = INF;
}
dp();
return 0;
}
'Algorithm > BOJ 문제풀이' 카테고리의 다른 글
[DP] 9252번 LCS2 (0) | 2019.02.07 |
---|---|
[DP] 9251번 LCS (0) | 2019.02.07 |
[DP] 2293번 동전1 (0) | 2019.02.06 |
[DP] 11052번 카드 구매하기 (0) | 2019.02.06 |
[DP] 1699번 제곱수의 합 (0) | 2019.02.06 |