카테고리 없음

[백준] 2133 타일 채우기 - Dynamic Programming / Java

graycode 2022. 9. 5. 22:13

 문제 링크

 

2133번: 타일 채우기

3×N 크기의 벽을 2×1, 1×2 크기의 타일로 채우는 경우의 수를 구해보자.

www.acmicpc.net

 

 풀이 과정

문제에 제시된 타일의 크기상 n 이 홀수인 경우에는 타일을 채울 수 없으므로,

n 이 짝수일 때만 경우의 수를 구한다.

 

n = 0 타일을 채울 수 있는 경우는 타일을 채우지 않는 경우의 수 1가지로 dp[0] = 1 으로 초기화,

n = 2 타일을 채울 수 있는 경우는 총 3가지로 dp[2] = 3,

n = 4 타일은 n = 2 의 각각의 경우에 * 3 을 한 dp[2] * 3 = 9 이다.

 

다만 n >= 4 부터 각각에 예외로 추가되는 경우의 수가 2가지씩 존재하므로

결과적으로 dp[4] = dp[2] * 3 + 2 = 11 이 성립한다.

 

n = 6 타일은 위에서 구해진 수식에 대입해보면 dp[6] = dp[4] * 3 + 2 가 구해지고,

6칸 중 4칸의 예외는 마찬가지로 2가지이며 이를 나머지 2칸의 모든 경우의 수와 곱하여 나머지 경우의 수를 구한다.

이를 수식으로 나타내면 dp[2] * 이 되며 해당 값을 dp[6] 에 더하여 모든 경우의 수를 구한다.

 

이런식으로 dp[8] = dp[6] * 3 + 2 + dp[4] * 2 + dp[2] * 2 로 나타낼 수 있으며

이를 2중 for 문의 i = 2 ~ n 범위 내부에 dp[i] = dp[i - 2] * 3,

j = i - 4 ~ 0 의 범위 내부에 dp[i] += dp[j] * 2 로 구현하고,

이때 +2 의 경우는 j = 0 일 때 dp[0] = 1 로 초기화하였으므로 1 * 2 = 2 로 구해진다.

 

이 후 3 * n 의 모든 타일을 채울 수 있는 경우의 수가 저장된 dp[n] 을 정답으로써 출력한다.

 

 풀이 코드

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;

public class Main {

    public static void main(String[] args) throws IOException {
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));

        int n = Integer.parseInt(br.readLine());
        int[] dp = new int[n + 1];

        dp[0] = 1;

        for (int i = 2; i <= n; i += 2) {
            dp[i] = dp[i - 2] * 3;
            for (int j = i - 4; j >= 0; j -= 2)
                dp[i] += dp[j] * 2;
        }

        bw.write(dp[n] + "\n");
        bw.flush();
    }

}