본문 바로가기
Programming/BOJ

백준 #1648 격자판 채우기(동적 계획법)

by 작은별하나(A Little Star) 2022. 9. 21.

이번 문제는 플래티넘으로 등급이 매겨진 문제입니다.

 

격자판의 크기가 주어지면, 2x1 미노로 격자판을 채우는 것입니다.  빈 곳이 있으면 안되고, 꽉 채우는 경우의 수를 계산하는 프로그램입니다.

 

일견 어려워보일 수 있겠지만, 동적 계획법을 잘 사용하면 쉽게 풀 수 있습니다.

 

2x1 미노를 세로 또는 가로로 채우는 문제이기 때문에 한줄을 다 채웠을 경우 다음줄에는 말끔하지 않게 되어 있을 수가 있습니다.  예를 들어서 3x6 격자판을 채운다고 해보죠.  첫줄을 채우는 방법은 다음의 두가지입니다.

 

           
         
         
         
           
         

 

두번째 줄의 모양에 따라서 안 채워진 곳은 0, 채워진 곳은 1이라고 한다면, 위의 두 패턴은 001과 100이 됩니다.

초기 패턴은 000이라고 할 수 있습니다.  그러면 우리는 점화식으로 다음과 같이 놓을 수 있습니다.  x 패턴에서 y패턴으로 갈 수 있다는 표현을 xy라고 한다면, 다음과 같이 점화식을 쓸 수 있습니다.

 

d0(m)=1

dy(m1)=xydx(m)

 

이렇게 하면, 3x6 격자판을 채울때 초기 패턴값 d000(6)=1이 되겠죠.

d100(5)=1,d001(5)=1,d111(5)=1이 될겁니다. 

이런식으로 다음줄도 계산하면, d000(4)=3,d011(4)=1,d110(4)=1이 될겁니다. 

다음은 d100(3)=4,d001(3)=4,d111(5)=3,

d000(2)=11,d011(2)=4,d110(2)=4,

d100(1)=15,d001(1)=15,d111(5)=11, 

d000(0)=41,d011(2)=15,d110(2)=15

 

이렇게 하면 3x6의 답은 41인 것을 알 수 있습니다.

 

두번째로 갈 수 있는 패턴인가 아닌가를 살펴보는 것은, 패턴을 반전한 다음, 연속된 1이 있는 경우 00을 만들어서 처리를 했습니다.  예를 들어서 현재 패턴이 001이라면 반전하면 110이 됩니다.  11이 연속된 1이므로, 나올 수 있는 패턴은 110, 000이 되는 것이죠.

 

그래서 나온 답들을 살펴보면,

14x14 : 990

13x12 : 1742

10x10 : 5606

 

이 답들을 참조해서 풀어보세요.

저는 파이썬의 딕셔너리를 이용해서 풀었습니다.  총 14x14가 있으니, 미리 답을 구해놓고 풀어도 될 듯 합니다.  좌우대칭이고, 곱한값이 짝수여야하므로, 총 77가지를 미리 계산하시면 O(1)로도 계산이 됩니다.  패턴이 2진수로 표현되므로, 전 패턴이 적게 나오는 쪽으로 진행을 했습니다.  즉, n, m 입력받은 것 중 작은 수를 이용해서 패턴에 사용했습니다.

 

반응형

댓글