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

[BOJ][C++] λ°±μ€€ 2421번: μ €κΈˆν†΅

선달 2024. 9. 24. 22:56
λ°˜μ‘ν˜•

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

 

문제

ν™νƒœμ„μ€ μ €κΈˆν†΅ 2개λ₯Ό 가지고 μžˆλ‹€. ν™νƒœμ„μ€ 맀일맀일 ν•˜λ‚˜μ˜ μ €κΈˆν†΅μ— 1원을 λ„£λŠ”λ‹€. 두 μ €κΈˆν†΅μ— λͺ¨λ‘ N원이 λͺ¨μ΄λ©΄ νƒœμ„μ΄λŠ” μƒˆλ‘œμš΄ μž₯λ‚œκ°μ„ μ‚΄ 수 있기 λ•Œλ¬Έμ—, μ €κΈˆμ„ λ©ˆμΆ˜λ‹€.

ν™νƒœμ„μ€ μ†Œμˆ˜λ₯Ό μ’‹μ•„ν•˜λŠ” κ²ƒμœΌλ‘œ μ„œκ°•λŒ€μ—μ„œ 유λͺ…ν•˜κΈ° λ•Œλ¬Έμ—, 첫째 μ €κΈˆν†΅μ— λ“€μ–΄μžˆλŠ” 돈의 μ–‘κ³Ό λ‘˜μ§Έ μ €κΈˆν†΅μ˜ 돈의 양을 μ΄μ–΄λΆ™μ˜€μ„ λ•Œ, 그것이 μ†Œμˆ˜κ°€ λ˜λŠ” 것을 λ„ˆλ¬΄λ‚˜λ„ μ’‹μ•„ν•œλ‹€.

예λ₯Ό λ“€μ–΄, 첫째 μ €κΈˆν†΅μ— 12원이 있고, λ‘˜μ§Έ μ €κΈˆν†΅μ— 7원이 μžˆλ‹€κ³  ν•˜μž. 그럼 κ·Έ 두 수λ₯Ό 이은 127은 μ†Œμˆ˜κ°€ λœλ‹€.

이제, μ΅œλŒ€ν•œ μ†Œμˆ˜κ°€ 많이 λ‚˜μ˜€λ„λ‘, ν™νƒœμ„μ΄ λˆμ„ λ„£λŠ” 졜적의 μˆœμ„œλ₯Ό μ°Ύμ•„λ‚΄λ©΄ λœλ‹€. κ°€μž₯ μ²˜μŒμ— 두 μ €κΈˆν†΅μ—λŠ” 1원씩 λ“€μ–΄μžˆλ‹€.

예λ₯Ό λ“€μ–΄,  N=4일 λ•Œλ₯Ό 보자.

1,1 → 2,1 → 2,2 → 3,2 → 3,3 → 4,3 → 4,4

μœ„μ™€κ°™μ΄ λˆμ„ λ„£μœΌλ©΄ μ†Œμˆ˜λŠ” 였직 1번 λ“±μž₯ν•œλ‹€. (43)

ν•˜μ§€λ§Œ, λ‹€μŒκ³Ό 같이 λˆμ„ λ„£μœΌλ©΄ μ†Œμˆ˜λŠ” 3번 (31,41,43) λ“±μž₯ν•˜κ²Œ λœλ‹€.

1,1 → 2,1 → 3,1 → 4,1 → 4,2 → 4,3 → 4,4

μœ„μ˜ μ˜ˆκ°€ N=4일 λ•Œ 의 닡이닀. κ°€μž₯ μ²˜μŒμ— 11은 세지 μ•ŠλŠ”λ‹€.

μž…λ ₯

첫째 쀄에 N이 주어진닀. (1<=N<=999)

좜λ ₯

첫째 쀄에 μ†Œμˆ˜κ°€ κ°€μž₯ 많이 λ‚˜μ˜€λŠ” μ €κΈˆ λ°©λ²•μ—μ„œ μ†Œμˆ˜κ°€ λ‚˜μ˜€λŠ” 횟수λ₯Ό 좜λ ₯ν•œλ‹€.

 

풀이

[i, j] λŠ” 무쑰건 [i-1, j] λ‚˜ [i, j-1] λ‘˜ 쀑 ν•œ 단계λ₯Ό κ±°μ³μ„œ μ˜¨λ‹€.

κ·Έλ ‡λ‹€λ©΄ [i,j]λŠ” μ € 두 κ²½μš°κ°€ κ±°μ³μ˜€λ©΄μ„œ 가진 μ†Œμˆ˜μ˜ 갯수λ₯Ό κ°€μ§ˆ 것이닀

그리고 [i,j]도 μ†Œμˆ˜λΌλ©΄ κ·Έ κ°―μˆ˜μ— 1을 λ”ν•œ 값을 가진닀.

즉, dp λ¬Έμ œλ‹€. 근데 이제 2차원을 곁듀인..

 

2차원 벑터 dpλ₯Ό λ§Œλ“€μ–΄μ€€λ‹€.

dp[i][j] = i와 jλ₯Ό 이어뢙인 값이 λ˜κΈ°κΉŒμ§€ λ‚˜μ˜¨ μ†Œμˆ˜μ˜ 갯수

이쀑 for문으둜 각 항을 λŒλ©΄μ„œ 직전 단계 λ‘κ°œ([i-1,j] [i,j-1])λ₯Ό λΉ„κ΅ν•˜λ©΄μ„œ dpλ₯Ό μˆ˜ν–‰ν•˜μž

두 단계쀑 더 큰 값을 κ³ λ₯΄κ³ , λ§Œμ•½ [i,j]κ°€ μ†Œμˆ˜λΌλ©΄ 1을 더해쀀닀.

 

그러기 μœ„ν•΄μ„œλŠ” ν•΄λ‹Ή ν•­([i,j])이 μ†Œμˆ˜μΈμ§€ μ—¬λΆ€λ₯Ό μ•Œμ•„ν•œλ‹€.

2차원 벑터 vλ₯Ό 또 λ§Œλ“€μ–΄μ€¬λ‹€.

v[i][j] = i와 jλ₯Ό 이어뢙인 값이 μ†Œμˆ˜μΈκ°€

 

vλ₯Ό μ±„μš°λ €λ©΄ i와 jλ₯Ό 이어뢙인 값을 κ΅¬ν•΄μ•Όν•œλ‹€.

두 수λ₯Ό λ¬Έμžμ—΄λ‘œ λ§Œλ“€μ–΄μ„œ λΆ™μ—¬μ£Όκ³  이λ₯Ό λ‹€μ‹œ μ •μˆ˜λ‘œ λ°”κΏ”μ£ΌλŠ” ν•¨μˆ˜λ₯Ό μ •μ˜ν–ˆλ‹€.

int connectedNum(int a, int b) {
    return stoi(to_string(a) + to_string(b));
}

 

이제 νŠΉμ • μˆ˜κ°€ μ†Œμˆ˜μΈμ§€ 여뢀도 μ•Œμ•„μ•Όν•œλ‹€. 벑터 ν•˜λ‚˜λ₯Ό λ§Œλ“€μž

isPrime[i] : iκ°€ μ†Œμˆ˜μΈκ°€?

    isPrime.assign(maxValue, true);
    isPrime[1] = false;
    for(int i=2; i*i<=maxValue; i++) {
        if(!isPrime[i]) {
            continue;
        }
        for(int j=i*i; j<=maxValue; j+=i) {
            isPrime[j] = false;
        }
    }

 

참고둜 n의 μ΅œλŒ“κ°’μ΄ 999λ‹€

이 경우 999999λΌλŠ” μˆ˜κΉŒμ§€ μ†Œμˆ˜ μ—¬λΆ€λ₯Ό ꡬ해놔야 μ œλŒ€λ‘œ 써먹을 수 μžˆλ‹€

isPrime을 nκΉŒμ§€λ§Œ κ΅¬ν•˜μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•˜μž

    int maxValue = connectedNum(n,n);

 

 

μ½”λ“œ

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

#include <iostream>
#include <vector>

using namespace std;

vector<bool>isPrime;

int connectedNum(int a, int b) {
    return stoi(to_string(a) + to_string(b));
}

int main() {
    int n;
    cin >> n;
    
    // isPrime[i] : iκ°€ μ†Œμˆ˜μΈκ°€?
    int maxValue = connectedNum(n,n);
    isPrime.assign(maxValue, true);
    isPrime[1] = false;
    for(int i=2; i*i<=maxValue; i++) {
        if(!isPrime[i]) {
            continue;
        }
        for(int j=i*i; j<=maxValue; j+=i) {
            isPrime[j] = false;
        }
    }
    
    // v[i][j] = i와 jλ₯Ό 이어뢙인 값이 μ†Œμˆ˜μΈκ°€
    vector<vector<bool>>v(n+1, vector<bool>(n+1, false));
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=n; j++) {
            int num = connectedNum(i, j);
            v[i][j] = isPrime[num];
        }
    }
    
    // dp[i][j] = i와 jλ₯Ό 이어뢙인 값이 λ˜κΈ°κΉŒμ§€ λ‚˜μ˜¨ μ†Œμˆ˜μ˜ 갯수
    vector<vector<int>>dp(n+1, vector<int>(n+1, 0));
    dp[1][1] = 0;
    for(int i=2; i<=n; i++) { // dp μ΄ˆκΈ°ν™”
        dp[1][i] = dp[1][i-1] + v[1][i];
        dp[i][1] = dp[i-1][1] + v[i][1];
    }
    for(int i=2; i<=n; i++) { // dp
        for(int j=2; j<=n; j++) {
            dp[i][j] = max(dp[i-1][j], dp[i][j-1]) + v[i][j];
        }
    }
    
    // 좜λ ₯
    cout << dp[n][n];
    
    return 0;
}
λ°˜μ‘ν˜•