[백준]/C++

백준 9048번 동전 [C++]

경우42 2024. 1. 11. 15:52
반응형

 

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

 

9084번: 동전

우리나라 화폐단위, 특히 동전에는 1원, 5원, 10원, 50원, 100원, 500원이 있다. 이 동전들로는 정수의 금액을 만들 수 있으며 그 방법도 여러 가지가 있을 수 있다. 예를 들어, 30원을 만들기 위해서는

www.acmicpc.net

#문제 해결 방법

 

간단하게 생각해보자

일단 시간복잡도를 계산하고 브루트 포스는 안된다는 결론을 내릴 수 있다.

그렇다면 dp를 사용해야 하는데

dp는 큰 문제를 작은문제로 쪼갤 수 있으며 

작은 문제를 통해 큰 문제를 풀 수 있어야 한다

 

즉 dp[i][j] 는 i번째 동전을 사용해서 j 의 값을 만드는 횟수인데

이 횟수는

i번째 동전을 사용하지 않은 문제로부터 답을 구할 수 있다. (작은문제에서 큰 문제의 해답을 구하기)

즉 i-1 번째 동전을 사용하고 j-coins[i] (동전의 값) 인 경우의수에서 

더해주면 답을 구할 수잇다.

 

이로부터 도출되는 점화식은 

for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= M; j++) {
                dp[i][j] = dp[i - 1][j];
                if (j >= coins[i]) {
                    dp[i][j] += dp[i][j - coins[i]];
                }
            }
        }

인 것이다.

 

#전체 코드

#include <iostream>
#include <vector>
using namespace std;

typedef long long ll;

int main() {
    int T;
    cin >> T;
    while (T--) {
        int N;
        cin >> N;

        vector<int> coins(N + 1);
        for (int i = 1; i <= N; i++) {
            cin >> coins[i];
        }

        int M;
        cin >> M;

        vector<vector<ll>> dp(N + 1, vector<ll>(M + 1, 0));
        for (int i = 0; i <= N; i++) {
            dp[i][0] = 1;
        }

        for (int i = 1; i <= N; i++) {
            for (int j = 1; j <= M; j++) {
                dp[i][j] = dp[i - 1][j];
                if (j >= coins[i]) {
                    dp[i][j] += dp[i][j - coins[i]];
                }
            }
        }

        cout << dp[N][M] << '\n';
    }

    return 0;
}
반응형