문제
45656이란 수를 보자.
이 수는 인접한 모든 자리의 차이가 1이다. 이런 수를 계단 수라고 한다.
N이 주어질 때, 길이가 N이면서 0부터 9까지 숫자가 모두 등장하는 계단 수가 총 몇 개 있는지 구하는 프로그램을 작성하시오. 0으로 시작하는 수는 계단수가 아니다.
https://www.acmicpc.net/problem/1562
난이도
골드 1
코드
import sys
n = int(sys.stdin.readline())
dp = [[[0 for _ in range(2**10)] for _ in range(10)] for _ in range(n+1)]
answer = 0
mod = 1000000000
for j in range(1,10) :
dp[1][j][1 << j] = 1
for i in range(1,n) : # n-1 번째 까지해서 다음 거 저장
for j in range(10) : # 마지막숫자
for k in range(2**10) : # 방문현황
tmp = dp[i][j][k] # 갯수
if j < 9 :
nextJ = j + 1
nextV = k | (1 << nextJ) # 방문처리
dp[i+1][nextJ][nextV] += tmp
dp[i+1][nextJ][nextV] %= mod
if j > 0 :
beforeJ = j - 1
nextV = k | (1 << beforeJ)
dp[i+1][beforeJ][nextV] += tmp
dp[i+1][beforeJ][nextV] %= mod
S = (1<<10)-1
for j in range(10) :
answer += dp[n][j][S]
answer %= mod
print(answer)
풀이
비트필드를 이용한 DP문제다.
dp배열 dp[i][j][k]를 만들어 풀었다.
i : 현재 자리수
j : 마지막 자리에 위치한 숫자
k : 현재까지 사용된 숫자들을 비트마스크로 표현한 값. 예를 들어 모든 값이 사용되었으면 0b11111111111 으로 표현된다.
초기상태는 j가 1부터 9까지 돌면서 해당 비트값을 1로 표현해 갯수를 1로 초기화했다.
0부터 시작하는건 세지 않기 때문에 제외
j가 0일때와 9일 때만 신경쓰면서 다음 자리수(j-1,j+1)의 마지막 자리 수를 방문처리하여 현재 값을 더해준다.
정답은 마지막 자리에 위치한 숫자가 0부터 9까지일 때 모든 숫자가 한번씩 사용된 경우의 수 (k가 0b11111111111 일 때) 를 모두 더해 답을 도출했다.
비트마스킹을 제대로 이용해 본 적은 거의 처음인것같다.
잘 익혀두면 유용하게 쓰일듯하다.
원래 값(value)에 num번 째 원소 추가
value |= (1 << num)
num번째 원소 삭제
value &= ~(1 << num)
'백준풀이' 카테고리의 다른 글
[Python] 백준 2263 트리의 순회 (0) | 2024.10.21 |
---|---|
[Python] 백준 2098 외판원 순원 (6) | 2024.10.18 |
[Python] 백준 1799 비숍 (0) | 2024.10.15 |
[Python] 백준 1509 팰린드롬 분할 (1) | 2024.10.15 |
[Python] 백준 17387 선분 교차 2 (3) | 2024.10.11 |