https://www.acmicpc.net/problem/1309
Problem
- 동물원 조련사의 머리가 아프지 않도록 우리가 2*N 배열에 사자를 배치하는 경우의 수가 몇 가지인지를 알아내는 프로그램을 작성해 주도록 하자.
조건
- 이 동물원에는 사자들이 살고 있는데 사자들을 우리에 가둘 때, 가로로도 세로로도 붙어 있게 배치할 수는 없다. 이 동물원 조련사는 사자들의 배치 문제 때문에 골머리를 앓고 있다.
- 사자를 한 마리도 배치하지 않는 경우도 하나의 경우의 수로 친다고 가정한다.
SOL
규칙성 발견하기
1부터 5까지 다 하고나서 알아낸 규칙입니다. 노가다 입니다. (진짜)
- F(n) = 2*F(n-1) + F(n-2) (n>=2)
- 이런 문제는 적어도 1~5까지는 해보는 편
#bottom up
N = int(input())
DP= [1,3] + [0]*(N-1)
for i in range(2,N+1):
DP[i] = (DP[i-2] + DP[i-1]*2)%9901
print(DP[N])
다른 시각으로 DP 스럽게 풀어보기
사자 우리는, 아무것도 없는 빈 우리로 끝나거나, 왼쪽철장에 사자가 있거나, 오른쪽 철장에 사자가 있는걸로 끝이난다.
그러므로, 3가지 상태의 이전 상태만 구해주면, 모든 경우의 수를 구하는게 된다.
정의
DP[n][0] = 빈 우리로 끝나는 경우
DP[n][1] = 왼쪽 철장에 사자가 있는 경우
DP[n][2] = 오른쪽 철장에 사자가 있는 경우
- 아무것도 없는 빈 우리로 끝나는 경우
- 그 전의 우리도 비어있을 수 있다. DP[n-1][0]
- 그 전의 우리는 왼쪽, 오른쪽에 모두 사자가 있을 수 있다. DP[n-1][1],DP[n-1][2]
- 왼쪽 철장에 사자가 있는 경우
- 그 전의 우리는 비어있을 수 있다. DP[n-1][0]
- 그 전의 우리에 오른쪽 철장에 사자가 있을 수 있다. DP[n-1][2]
- 오른쪽 철장에 사자가 있는 경우
- 그 전의 우리는 비어있을 수 있다.DP[n-1][0]
- 그 전의 우리는 왼쪽 철장에 사자가 있을 수 있다. DP[n-1][1]
점화식
DP[n][0] = DP[n-1][0] + DP[n-1][1]+DP[n-1][2]
DP[n][1] = DP[n-1][0] + DP[n-1][2]
DP[n][2] = DP[n-1][0] + DP[n-1][1]
#bottom up
import sys
input = sys.stdin.readline
N = int(input())
DP = [[0]*(3) for _ in range(N+1)]
#inital value
DP[1][0] = 1
DP[1][1] = 1
DP[1][2] = 1
for i in range(2, N + 1):
DP[i][0] = (DP[i - 1][0] + DP[i - 1][1] + DP[i - 1][2]) % 9901
DP[i][1] = (DP[i - 1][0] + DP[i - 1][2]) % 9901
DP[i][2] = (DP[i - 1][0] + DP[i - 1][1]) % 9901
print(sum(DP[N]) % 9901)
'알고리즘 문제(SOL)' 카테고리의 다른 글
[백준/1495/파이썬] 기타리스트 (0) | 2022.01.18 |
---|---|
[백준/1720/파이썬] 타일코드 (0) | 2022.01.18 |
[백준/2240/파이썬] 자두나무 (0) | 2022.01.17 |
[백준/11066/파이썬] 파일 합치기 (0) | 2022.01.17 |
[백준/11049/파이썬] 행렬 곱셈 순서 (0) | 2022.01.17 |