πŸ•οΈ ICPC Sinchon/Dynamic Programming

[BOJ][C++] λ°±μ€€ 2293번: 동전 1

선달 2023. 11. 24. 14:08
λ°˜μ‘ν˜•

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

 

2293번: 동전 1

첫째 쀄에 n, kκ°€ 주어진닀. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) λ‹€μŒ n개의 μ€„μ—λŠ” 각각의 λ™μ „μ˜ κ°€μΉ˜κ°€ 주어진닀. λ™μ „μ˜ κ°€μΉ˜λŠ” 100,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

www.acmicpc.net

 

문제

n가지 μ’…λ₯˜μ˜ 동전이 μžˆλ‹€. 각각의 동전이 λ‚˜νƒ€λ‚΄λŠ” κ°€μΉ˜λŠ” λ‹€λ₯΄λ‹€. 이 동전을 μ λ‹Ήνžˆ μ‚¬μš©ν•΄μ„œ, κ·Έ κ°€μΉ˜μ˜ 합이 k원이 λ˜λ„λ‘ ν•˜κ³  μ‹Άλ‹€. κ·Έ 경우의 수λ₯Ό κ΅¬ν•˜μ‹œμ˜€. 각각의 동전은 λͺ‡ κ°œλΌλ„ μ‚¬μš©ν•  수 μžˆλ‹€.

μ‚¬μš©ν•œ λ™μ „μ˜ ꡬ성이 같은데, μˆœμ„œλ§Œ λ‹€λ₯Έ 것은 같은 κ²½μš°μ΄λ‹€.

μž…λ ₯

첫째 쀄에 n, kκ°€ 주어진닀. (1 ≤ n ≤ 100, 1 ≤ k ≤ 10,000) λ‹€μŒ n개의 μ€„μ—λŠ” 각각의 λ™μ „μ˜ κ°€μΉ˜κ°€ 주어진닀. λ™μ „μ˜ κ°€μΉ˜λŠ” 100,000보닀 μž‘κ±°λ‚˜ 같은 μžμ—°μˆ˜μ΄λ‹€.

좜λ ₯

첫째 쀄에 경우의 수λ₯Ό 좜λ ₯ν•œλ‹€. 경우의 μˆ˜λŠ” 231보닀 μž‘λ‹€.

 

풀이

dpλ¬Έμ œκΈ΄ν•œλ° 쑰금 생각이 ν•„μš”ν•˜λ‹€

μ˜ˆμ œμ— λ‚˜μ™€μžˆλŠ” 1,2,5μ›μœΌλ‘œ 10(k)원을 λ§Œλ“œλŠ” κ²½μš°λ“€μ„ μƒκ°ν•΄λ³΄μž

 

1원 | 1
2원 | 11 2
3원 | 111 21
4원 | 1111 211 22
5원 | 11111 2111 221 5
6원 | 111111 21111 2211 222 51
7원 | 1111111 211111 22111 2221 511 52
8원 | 11111111 2111111 221111 22211 5111 521 2222
9원 | 111111111 21111111 2211111 222111 51111 5211 22221 522
10원 | 1111111111 211111111 22111111 2221111 511111 52111 222211 5221 22222 55

 

a. 1μ›μœΌλ‘œλ§Œ λ§Œλ“€ 수 μžˆλŠ” 경우 - νŒŒλž‘

b. 1원과 2μ›μœΌλ‘œ λ§Œλ“€ 수 μžˆλŠ” 경우 - κ²€μ •

c. 1원과 2원과 5μ›μœΌλ‘œ λ§Œλ“€ 수 μžˆλŠ” 경우 - λΉ¨κ°•

 

μ„Έ 경우λ₯Ό λ”°λ‘œ μƒκ°ν•΄μ€˜μ•Ό 쀑볡을 방지할 수 μžˆλ‹€

a b c의 경우λ₯Ό 순차적으둜 κ΅¬ν•˜μž

 

dp[i] = i원을 λ§Œλ“€ 수 μžˆλŠ” 경우의 수

a ) 1 1 1 1 1 1 1 1 1 1 
b ) 1 2 2 3 3 4 4 5 5 6 
c ) 1 2 2 3 4 5 6 7 8 10 

 

// 풀이 : https://whkakrkr.tistory.com

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n,k;
    cin >> n >> k;
    vector<int>v;
    for(int i=0; i<n; i++) {
        int tmp;
        cin >> tmp;
        if(tmp>k) continue;
        v.push_back(tmp);
    }
    n = v.size();
    sort(v.begin(), v.end());
    
    vector<long long>dp(k+1, 0);
    for(int i=0; i<n; i++) {
        int coin = v[i];
        dp[coin]++;
        for(int j=coin+1; j<=k; j++) {
            dp[j] += dp[j-coin];
        }
    }
    
    cout << dp[k];
 
}​

 

 

 

μ‹œν–‰μ°©μ˜€ - λ©”λͺ¨λ¦¬μ΄ˆκ³Ό

2차원 dpλ₯Ό μ΄μš©ν•˜μ—¬ κ΅¬ν˜„ν•œ 방식 λ©”λͺ¨λ¦¬ μ΄ˆκ³Όκ°€ λœ¨λ”λΌ..

 

1원 | 1
2원 | 11 2
3원 | 111 21
4원 | 1111 211 22
5원 | 11111 2111 221 5
6원 | 111111 21111 2211 222 51
7원 | 1111111 211111 22111 2221 511 52
8원 | 11111111 2111111 221111 22211 5111 521 2222
9원 | 111111111 21111111 2211111 222111 51111 5211 22221 522
10원 | 1111111111 211111111 22111111 2221111 511111 52111 222211 5221 22222 55

 

1원(첫번째 동전)이 ν•œλ²ˆμ΄λΌλ„ ν¬ν•¨λ˜λ©΄ 검정색

1원 포함 μ•ˆν•˜κ³  2원(λ‘λ²ˆμ§Έ 동전)이 ν•œλ²ˆμ΄λΌλ„ ν¬ν•¨λ˜λ©΄ νŒŒλž€μƒ‰
1원과 2원 포함 μ•ˆν•˜κ³  5원(μ„Έλ²ˆμ§Έ 동전)이 ν•œλ²ˆμ΄λΌλ„ ν¬ν•¨λ˜λ©΄ 빨강색

 

v[i] = i번째 λ™μ „μ˜ κ°’dp[k][i] = i번째 동전과 κ·Έ λ‹€μŒ λ™μ „λ“€λ‘œλ§Œ K원을 λ§Œλ“€ 수 μžˆλŠ” 경우의 수 둜 λ’€λ‹€

 

즉 μ˜ˆμ œμ—μ„œλŠ”dp[k][0] = dp[k-1][0] + dp[k-2][1] + dp[k-5][2];dp[k][1] = dp[k-2][1] + dp[k-2][2];dp[k][2] = dp[k-5][2];

 

κΈˆμ•‘ 1 2 3 4 5 6 7 8 9 10
κ²€μ • 1 1 2 2 3 4 5 6 7 8
νŒŒλž‘ 0 1 0 1 0 1 1 1 1 1
λΉ¨κ°• 0 0 0 0 1 0 0 0 0 1

 

// 풀이 : https://whkakrkr.tistory.com

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int main() {
    int n,k;
    cin >> n >> k;
    vector<int>v(n);
    vector<vector<long long>>dp(k+1, vector<long long>(n, 0));
    for(int i=0; i<n; i++) {
        cin >> v[i];
    }
    sort(v.begin(), v.end());
    for(int i=0; i<n; i++) {
        if(v[i]>k) break;
        dp[v[i]][i] = 1;
    }
    
    for(int i=1; i<k+1; i++) {
        for(int j=0; j<n; j++) {
            int coin = v[j];
            if(i-coin <= 0) break;
            
            int sum = 0;
            for(int h=j; h<n; h++) {
                dp[i][j] += dp[i-coin][h];
            }
        }
    }
    
    long long ans = 0;
    for(int i=0; i<n; i++) {
        ans += dp[k][i];
    }
    cout << ans;
 
}

 

λ°˜μ‘ν˜•