본문 바로가기

백준

[DP] 다이나믹 프로그래밍 타일링 문제 (11726, 11727, 2133)

11726

위 문제를 그림으로 나타내면 아래와 같다.

이와 같이 2*n의 타일을 2*1과 1*2 타일로 채워넣으면 되는 것이다.

처음 다이나믹 프로그래밍을 배우고 푸는 문제라 직접 경우의 수를 다 따져가며.. ㅎㅎ.. 풀려고 했었다.. (삽질)

이는 너무 복잡하게 생각할 필요없이 아래와 같이 풀면 된다.

말로 설명해보면, 2*n의 타일을 채우는 것은 결국 2*n-1의 타일에 2*1을 하나 붙인 것과 2*n-2 타일에 1*2 타일을 두개 붙인 것과 같기 때문에, 이를 점화식으로 쓰면 D[n] = D[n-1] + D[n-2] 과 같게 된다.

이를 코드로 작성하면 아래와 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int t[1001];
 
int tile(int n) {
    if (n == 1)
        return 1;
    if (n == 2)
        return 2;
    else if (t[n] != 0)
        return t[n];
    return t[n] = (tile(n - 1+ tile(n - 2)) % 10007;
}
 
int main() {
    int n;
    scanf("%d"&n);
    if (n == 0)
        return 0;
    printf("%d", tile(n));
    return 0;
}
cs

 

그럼 이제 이와 비슷한 11727을 풀어보도록 하자.

 

 

11717

위 문제를 그림으로 나타내면 아래와 같다.

11726과 같은 경우에서, 2*2 타일로 채우는 경우가 추가한 것이다.

이 문제는 아래와 같이 풀 수 있다.

말로 설명해보면, 2*n의 타일을 채우는 것은 결국 2*n-1의 타일에 2*1을 하나 붙인 것과 2*n-2 타일에 1*2 타일을 두개 붙이거나 2*2 타일을 하나 붙이는 것과 같기 때문에, 이를 점화식으로 쓰면 D[n] = D[n-1] + 2*D[n-2] 과 같게 된다.

이를 코드로 작성하면 아래와 같다.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int t[1001];
 
int tile(int n) {
    if (n == 1)
        return 1;
    if (n == 2)
        return 3;
    else if (t[n] != 0)
        return t[n];
    return t[n] = (tile(n - 1+ 2*tile(n - 2)) % 10007;
}
 
int main() {
    int n;
    scanf("%d"&n);
    if (n == 0)
        return 0;
    printf("%d", tile(n));
    return 0;
}
cs

 

그럼 이를 토대로 조금 더 심화문제 2133을 풀어보자

 

2133

위 문제도 그림으로 나타내면 아래와 같다.

앞서 두 문제와 다른 점이 있다면, 2*n 이 아니라 3*n인 것이다.

이 문제는 아래와 같은 방식으로 해결할 수 있다.

말로 설명해보면, 3*n의 타일을 채우는 것은 결국 3*n-2의 타일에 세가지의 경우로 3*2를 채우는 경우와

3*n-4 타일에 그림과 같은 경우로 3*4를 채우는 경우로 나뉠 수 있다. 그러나 이 문제인 경우, 앞서 말한 n-4일 때와 같이 n-a에서 a가 4이상의 짝수일때 2가지의 경우가 더 생기므로, 이를 점화식으로 나타내면

D[n] = 3*D[n-2] + (2*D[n-4]+2*D[n-6]+...+2*D[0])

 같게 된다.

이를 코드로 작성하면 아래와 같다.

 

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
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
 
int t[31];
 
int tile(int n) {
    int result = 0;
    if (n == 0)
        return 1;
    if (n == 1)
        return 0;
    if (n == 2)
        return 3;
    else if (t[n] != 0)
        return t[n];
    result = (3 * tile(n - 2));
    for (int i = 3; i <= n; i++) {
        if (i % 2 == 0)
            result += 2*tile(n - i);
    }
    return t[n] = result;
}
 
int main() {
    int n;
    scanf("%d"&n);
    printf("%d", tile(n));
    return 0;
}
cs

 

이렇듯 오늘은 dp 3문제를 풀어보았다(사실 풀기는 한참 전에 풀었다)

dp를 모른채로 듣기만 하였을때는 먼가.. 이름이 어려워보였는데 막상 해보니 할만 한 거 같다 (걍 쉬운 문제라 그럴수도)

아무튼 앞으로 이를 참고해서 dp와 관련된 문제를 몇개 더 풀어봐야겠다는 생각이 들었다.