백준의 2xn 타일링(11726) 문제이다.
[ 문제 바로가기 ]
[ 문제풀이 ]
2xn 크기의 직사각형을 2 x 1 타일과, 1 x 2 타일로 채우는 방법의 수를 구하는 문제이다.
먼저 크기가 작은 직사각형부터 알아보고 이를 통해서 하나의 정형화된 식을 도출해보자.
가장 먼저 2 x 1 크기의 직사각형을 채우는 방법의 수를 구해보자.
2 x 1 크기의 직사각형이니, 1 x 2 로는 채울 수가 없고, 2 x 1 크기의 직사각형 한 개를 이용해서 채우는 방법 한 가지가 있다.
2 x 1 크기의 직사각형 = 1가지
2 x 2 크기의 직사각형을 구해보자. 2 x 2 직사각형의 경우 다음과 같이 2가지 방법으로 채울 수가 있다.
.
위의 그림과 같이 1 x 2 타일을 2개 이용하는 방법과 , 2 x 1 타일을 2개 이용하는 방법 총 2가지 방법이 존재한다.
2 x 2 크기의 직사각형 = 2가지
그럼, 2 x 3 크기의 직사각형을 채워보자.
.
위와 같이 3가지 방법으로 2 x 3 크기의 직사각형을 채울 수 있다.
그런데 위의 그림은 다음과 같은 그림으로 생각해 볼 수 있다.
.
가장 왼쪽 그림부터 1번 , 2번 , 3번 그림이라고 가정해보자.
그런데 1번 그림과 2번 그림은 공통된 부분이 하나 있다. 바로 "2 x 3 직사각형을 채우기 위해서 , 2 x 2 직사각형의 가장 오른쪽에 2 x 1 타일을 추가한 것" 이라는 것이다.
물론 ! 1번 그림과 2번 그림에서 왼쪽에 있는 2 x 2 직사각형을 채우는 방법은 달랐지만 , 그 방법이 어떤 방법이든지 간에 가장 오른쪽에 2 x 1 타일을 하나 더 추가한 형태를 가지고 있게 된다.
그럼 3번 그림은 어떤 특징을 가지고 있을까 ?? 바로 "2 x 3 직사각형을 채우기 위해서 , 1 x 2 짜리 타일을 2개 추가한 것" 이라는 특징을 가지고 있다.
이 정도만 알고, 2 x 4 크기의 직사각형을 채워보자. 2 x 4 크기의 직사각형은 다음과 같은 방법으로 채울 수 있다.
위와 같이 5가지 방법으로 채울 수가 있다. 위의 그림을 다시 한번 특징을 볼 수 있도록 가져와보면 다음과 같다.
마찬가지로 왼쪽에서 부터 1 ~ 5번의 그림이라고 표현해보자.
1번 ~ 3번 그림은 공통된 특징을 하나 가지고 있다.
바로, "2 x 4 직사각형을 채우기 위해서 , 2 x 3 직사각형의 가장 오른쪽에 2 x 1 타일을 추가한 것" 이라는 것이다.
4번 ~ 5번 그림 또한 공통된 특징을 하나 가지고 있다.
바로, "2 x 4 직사각형을 채우기 위해서 , 2 x 2 직사각형의 가장 오른쪽에 2 x 2 타일을 추가한 것" 이라는 것이다.
위에서 이야기했던 2 x 3 직사각형을 채울 때와, 2 x 4 직사각형을 채울 때를 잘 비교해보면 하나의 정형화된 식을 생각해볼 수 있다. 바로 2 x N 크기의 직사각형을 채울 수 있는 방법의 수는 2 x (N - 2) 크기의 직사각형을 채울 수 있는 방법의 수 + 2 x (N - 1)크기의 직사각형을 채울 수 있는 방법의 수 라는 것이다.
위의 식이 적용이 되는지 직접확인해 보자.
2 x 1 크기의 직사각형을 채우는 방법의 수 = 1 가지
2 x 2 크기의 직사각형을 채우는 방법의 수 = 2 가지
2 x 3 크기의 직사각형을 채우는 방법의 수 = 3 가지 = 2 x 1 크기의 직사각형을 채울 수 있는 방법의 수(1) + 2 x 2 크기의 직사각형을 채울 수 있는 방법의 수(2)
2 x 4 크기의 직사각형을 채우는 방법의 수 = 5가지 = 2 x 2 크기의 직사각형을 채울 수 있는 방법의 수(2) + 2 x 3 크기의 직사각형을 채울 수 있는 방법의 수(3)
위의 식이 그대로 적용되는 것을 확인할 수 있다.
2 x (N - 2)크기의 직사각형을 채울 수 있는 방법의 수와, 2 x (N - 1)크기의 직사각형을 채울 수 있는 방법의 수를 단순히 더하는 이유는 우리가 구하고자 하는 값이 "해당 크기의 직사각형을 채울 수 있는 "방법의 수" 이기 때문이다. "사용한 타일의 갯수" 가 아니기 때문이다."
즉, 2 x N 크기의 직사각형을 채울 수 있는 방법의 수는 2 x (N - 2)크기의 직사각형을 채운 상태에서, 1 x 2 크기의 타일을 2개를 붙이는 경우와 2 x (N - 1)크기의 직사각형을 채운 상태에서, 2 x 1 크기의 타일을 1개를 붙이는 경우이다.
따라서 본인은 위의 내용을 구현하기 위해서 DP[] 라는 1차원 배열을 사용해 주었는데, DP[a] = b의 의미는 "2 x a 크기의 직사각형을 채울 수 있는 방법의 수는 b가지 입니다." 를 의미한다.
가장 먼저 초기식으로는 DP[1] = 1과 DP[2] = 2를 설정해주었다.
점화식으로는 위에서 도출한 결과인 DP[N] = DP[N - 1] + DP[N - 2] 로 설정해 주었다.
이해를 돕기위해서 위의 그림과 이 점화식을 같이 표현해보면 다음과 같이 표현할 수 있다.
아래의 그림은 2 x 4 크기의 직사각형을 채우는 방법이다.
. 위와 같이 표현해볼 수 있다.
다시한번 정리하자면, 2 x N 크기의 직사각형을 채울 수 있는 방법의 수는, 2 x (N - 2) 크기의 직사각형을 채워놓고, 그 오른쪽에 1 x 2 크기의 직사각형 2개를 붙이는 경우와 2 x (N - 1)크기의 직사각형을 채워놓고, 그 오른쪽에 2 x 1 크기의 직사각형 1개를 붙이는 경우의 합으로 나타낼 수 있다.
[ 소스코드 ]
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | #include <iostream> #define endl "\n" #define MAX 1010 #define MODULER 10007 using namespace std; int N; int DP[MAX]; void Input() { cin >> N; } void Solution() { DP[1] = 1; DP[2] = 2; for (int i = 3; i <= N; i++) { DP[i] = DP[i - 1] + DP[i - 2]; DP[i] = DP[i] % MODULER; } cout << DP[N] << endl; } void Solve() { Input(); Solution(); } int main(void) { ios::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); //freopen("Input.txt", "r", stdin); Solve(); return 0; } | cs |
'[ BOJ Code ] > # BOJ -' 카테고리의 다른 글
[ 백준 2579 ] 계단 오르기 (C++) (5) | 2020.07.26 |
---|---|
[ 백준 1149 ] RGB 거리 (C++) (1) | 2020.07.24 |
[ 백준 1003 ] 피보나치 함수 (C++) (0) | 2020.07.22 |
[ 백준 1463 ] 1로 만들기 (C++) (0) | 2020.07.21 |
[ 백준 19235 ] 모노미노도미노 (C++) (7) | 2020.06.19 |