본문으로 바로가기

[DP] 2294번 동전2

category Algorithm/BOJ 문제풀이 2019. 2. 6. 15:27
2294_동전2

2294번 동전 2

 

https://www.acmicpc.net/problem/2294


 

문제

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