[백준/C++] 10844번 - DP (설명 포함)

2025. 11. 4. 15:37·PS/BaekJoon

문제 접근 

일단 주어진 테스트 케이스에 맞춰서 상황을 살펴봤다.

N = 1)
1 / 2/ 3/ 4/ 5/ 6/ 7/ 8/ 9

N = 2)
10 12 21 23 32 34 43 45 54 56 65 67 76 78 87 89 98 
0 - 1
1 - 0,2
2 - 1,3
3 - 2,4
4 - 3,5
5 - 4,6
6 - 5,7
7 - 6,8
8 - 7,9
9 - 8

N = 3)
101 
123 121 
234 232 
212 210
321 323
...

 

보면 자기 자신에 +1,-1 한 숫자들 만큼이 인접한 숫자가 된다.

그래서 0이나 9일 떄는 1개씩밖에 못 더해준다. (0일 떄는 -1을 못하고, 9일 떄는 +1을 못하기 떄문)

보면 N=2일 때의 값은, N=1인 숫자들에 +2 씩 해주고, 9일 때만 +1 해주면 된다.

 

N이 몇자리 수 이든간에, 가장 오른쪽에 있는 숫자에 맞춰서 +1,-1을 해주면된다.

N-1 자리 수까지는 다 연속된 수로 구성되어 있다고 생각하고 진행할 것이기 떄문이다.

 


일반화

d[i][j] += d[i-1][j-1] + d[i-1][j+1];

 

 

i는 N자리수를 의미한다고 보면 된다. 

j는 0~9까지이고, 위의 일반화 식에는 중요한 조건이 있다.

 

j가 0이라면 d[i-1][j-1]을 더해주면 안되고, (0에서 하나 더 작은 수는 -1로 음수가 되므로)

j가 9라면 d[i-1][j+1]을 더해주면 안된다. (9에서 하나 더 큰 수는 10으로 한자리수 가 아니므로)

 

 

초기조건

d[1][1] ~ d[1][9] = 1 로 초기 설정을 해주면 된다.

 

예시

  • d[2][3] += d[1][3+1] + d[1][3-1];

2자리 자연수 중에서 계단 수를 찾는 것이다.

그 중에서 j=3이니까, 3으로 시작하는 두자리 자연수 중 계단 수의 개수를 찾는 항이라고 보면 된다.

3의 옆에는 4나 2가 올 수 있고, N이 2인 상태에서는 N-1=1의 상태를 참고해 나갈 것이므로

N이 1일 때 4와 2의 계단 수 개수를 더해주면 된다.

(34 = 1개) + (32 = 1개) = 2개

 

  • d[3][3] += d[2][3+1] + d[2][3-1]

하나 더 봐보자. 3자리 자연수 중에서 3으로 시작하는 계단 수를 찾고 싶다.

그리고 2자리 자연수 중 3과 연속된 숫자인 4와 2로 시작하는 계단수를 이용해서 찾아가려고 한다.

이미 반복문을 통해서 d[2][j]가 다 완성되어 있을테니 바로 계산이 가능해진다.

 

한 마디로, 3으로 시작하는 계단수를 찾기 위해서, 3의 양 옆 연속된 숫자들의 계단수로 쪼개서 찾아가는 거다.

1. 3으로 시작하는 계단 수 찾을래 
2. 34_ OR 32_ 이런 상황이네.
3. 그러면 일단 4_ 와 2_를 해결하자. 어 그러면 N=2인 4의 계단수 찾는게 되네? (d[2][4]와 d[2][2] 찾는 문제로 작아짐)
  3-1. 4다음에는 5나 3일 올 수 있네. 어 그러면 한 번 더 쪼개서 N=1인 5와 3의 계단수를 찾으면 d[2][4]=2가 되네
  3-2. 2다음에는 1이나 3이 올 수 있네. 어 그러면 한 번 더 쪼개서 N=1인 1과 3의 계단수를 찾아 더하면 d[2][2] =2 가 되네
4. 자 그러면 다시 3번으로 돌아가면 4_ 와 2_로 시작하는 계단 수는 4개가되고
    2번의 문제도 해결한 상태가 되네? 답은 4개!

 

>> 345 - 343 - 323 - 321

 

구현

#include <bits/stdc++.h>
using namespace std;

int n;
long long d[101][10];
int main(){
    ios::sync_with_stdio(0); cin.tie(0);
    //d[i][j] = i 자리 수 일 때, j의 인접 수 개수 
    cin >> n;
    
    //초기화
    for (int i=1;i<=9;++i){
        d[1][i]=1;
    }

    for(int i=2;i<=n;++i){
        for (int k=0;k<=9;++k){
            if (k!=0) d[i][k] += d[i-1][k-1];
            if (k!=9) d[i][k] += d[i-1][k+1];
            d[i][k]%=1000000000;
        }
    }

    long long ans = 0;
    for (int i=0;i<=9;++i){
        ans+=d[n][i];
    }
    ans%=1000000000;
    cout<<ans;
}

 

 

dp는 점화식을 세우는게 어렵다.

적당히 1차원 배열도 쓰고, 2차원 배열도 같이 써야하는 것 같ㄷ..r

저작자표시 비영리 변경금지 (새창열림)

'PS > BaekJoon' 카테고리의 다른 글

[백준/C++] 11055번 - DP (설명 포함)  (0) 2025.11.05
[백준/C++] 1932번 - DP  (0) 2025.10.24
[백준/C++] 2468번 - BFS  (7) 2025.08.06
'PS/BaekJoon' 카테고리의 다른 글
  • [백준/C++] 11055번 - DP (설명 포함)
  • [백준/C++] 1932번 - DP
  • [백준/C++] 2468번 - BFS
Lyv
Lyv
  • Lyv
    inimizi
    Lyv
  • 전체
    오늘
    어제
    • 분류 전체보기 (60)
      • 이것저것 도전 (5)
        • 공모전 (0)
        • 우테코 (5)
      • PS (16)
        • 삼성기출 (2)
        • LeetCode & Codility (4)
        • Programmers (6)
        • BaekJoon (4)
      • 공부기록 (33)
        • CS (16)
        • 영어 (1)
        • iOS (1)
        • 프로그래밍 언어 (0)
        • Web (4)
        • Linux (1)
        • Docker (2)
        • Network (4)
        • IaC (3)
      • 프로젝트 경험 (0)
      • DailyLog (4)
      • 취준Log (0)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    DP
    C++
    정처기
    우테코프리코스
    공부기록
    정처기실기
    FastAPI
    문제풀이
    자동화
    디자인패턴
    manifest
    PS
    운영체제
    리눅스
    우테코
    이미지
    프로그래머스
    os
    c언어
    til
    프리코스회고
    스케줄링
    대학생
    IAC
    네트워크
    ansible
    컨테이너
    코테
    운영체제intro
    백준
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.5
Lyv
[백준/C++] 10844번 - DP (설명 포함)
상단으로

티스토리툴바