BOJ C++ 알고리즘 공부

[DP] 오르막 수 (11057)(C++)

kk_eezz 2024. 1. 24. 01:32

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

 

11057번: 오르막 수

오르막 수는 수의 자리가 오름차순을 이루는 수를 말한다. 이때, 인접한 수가 같아도 오름차순으로 친다. 예를 들어, 2234와 3678, 11119는 오르막 수이지만, 2232, 3676, 91111은 오르막 수가 아니다. 수

www.acmicpc.net

 

1. 문제 개요

 

수의 자리가 오름차순을 이루는 수를 오르막 수라고 할때, 수의 길이 N으로 만들 수 있는 오르막 수의 개수를 구하는 문제. 이때, 인접한 수가 같아도 오름차순으로 친다. 예를 들어, 1234, 1113 등이 오르막 수이다.

 

 

2. 입출력

 

 

 

3. 문제 풀이

 

N*M의 2차원 배열을 사용하여 N자리 오르막 수 중 숫자 M으로 끝나는 수의 개수를 구한 후, M=0부터 M=9까지를 합하여 정답을 구하였다. 2차원 배열은 다음과 같다.

 

  0 1 2 3 4 5 6 7 8 9
1 1 1 1 1 1 1 1 1 1 1
2 1 2 3 4 5 6 7 8 9 10
3 1 3 6 10 15 21 28 36 45 55

 

여기서 규칙은 다음과 같다. N자리 오르막 수 중 숫자 M으로 끝나는 수의 개수는 N-1자리 오르막 수 중에서 숫자 M과 같거나 작은 수로 끝나는 수의 합과 같다. 예를 들어 세 자리 오르막 수 중에 숫자 1으로 끝나는 수는 두 자리 오르막 수 중에 숫자 1로 끝나는 수와 숫자 0으로 끝나는 수의 합이므로 1+2=3이된다. 따라서 list[i][j] = list[i-1][j] + list[i-1][j-1] + list[i-1][j-2] ... 과 같이 표현할 수 있으며 이를 다르게 표현하면 list[i][j] = list[i-1][j] + list[i][j-1]이 된다.

 

이를 코드로 나타내면 다음과 같다. 재귀함수로 구현하였다.

 

int DP(int n, int idx) {
    if(n==1)
        return 1;
    if(idx==0)
        return 1;
    if(list[idx][n])
        return list[idx][n];

    list[idx][n] = DP(n-1,idx) + DP(n,idx-1);
    
    return list[idx][n]%10007;
}

 

 

4. 전체 코드

 

#include <algorithm>
#include <iostream>

using namespace std;

const int MAX = 1001;
int list[10][MAX];

int DP(int n, int idx) {
    if(n==1)
        return 1;
    if(idx==0)
        return 1;
    if(list[idx][n])
        return list[idx][n];

    list[idx][n] = DP(n-1,idx) + DP(n,idx-1);
    
    return list[idx][n]%10007;
}

int main(void) {
    int N;
    scanf("%d",&N);
    
    int ans = 0;
    for(int i=0;i<10;i++)
        ans += DP(N,i);
    
    printf("%d\n",ans%10007);
}

 

아직 배워가는 중이라 틀린 부분이 있을 수 있습니다. 지적할 부분이 있다면 댓글로 알려주시면 감사하겠습니다!!!