Programming Problem/동적 계획법(Dynamic Programming)
[Java] 백준 11726번 2×n 타일링 (DP)
거북고래
2023. 6. 18. 15:19
반응형
[Java] 백준 11726번 2×n 타일링 (DP)
□ 문 제
2×n 크기의 직사각형을 1×2, 2×1 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오.
아래 그림은 2×5 크기의 직사각형을 채운 한 가지 방법의 예이다.
○ 입 력
첫째 줄에 n이 주어진다. (1 ≤ n ≤ 1,000)
○ 출 력
첫째 줄에 2×n 크기의 직사각형을 채우는 방법의 수를 10,007로 나눈 나머지를 출력한다.
[문제 링크] 백준 11726번 2×n 타일링
□ 문제풀이
n이 1, 2, 3, 4, 5일 때를 직접 그려보면 아래의 규칙을 가짐을 알 수 있다.
dp[n] = dp[n - 1] + dp[n - 2]
결과론적으로 2 X n 크기의 직사각형을 채울 수 있는 경우의 수는 2 X (n - 1)일 때 그릴 수 있는 모양에서 우측에 세로 하나짜리를 그린 것과 2 X (n - 2)일 때 그릴 수 있는 모양에서 우측에 가로 두 줄짜리를 넣은 경우와 같다.
하지만 왜 이렇게 되는 것인지 수학적인 점화식을 구해보고 싶었으나 실패했다. 다만 2 X n 크기에서 채우는 경우의 수를 단독으로 알 때는 동자순열을 통해 수학적으로 구할 수 있음을 알아냈다.
또 이해가 가지않는 것은 혼자 풀이할 때에는 DP 배열에 점화식의 내용을 반영하여 저장했다. 그런데 아무리 제출해도 틀렸다고 나오길래 왜 그런가 다른 분들의 풀이를 참조하니, 저장할 때도 10007을 나누고 그 나머지를 저장한다..?
일단 맞추기 위해 나 또한 그런 풀이로 바꾸었으나 이해는 가지 않는다..
참고사항
전체 코드
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
public class Main {
static int num;
static long answer;
static final int MAX = 1000;
static long[] dp = new long [MAX + 1];
public static void main(String[] args) throws NumberFormatException, IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
num = Integer.parseInt(br.readLine());
dp[1] = 1;
dp[2] = 2;
// answer = bottomUp(num);
answer = topDown(num);
bw.write(String.valueOf(answer));
bw.flush();
bw.close();
br.close();
}
static long bottomUp(int n) {
if(n > 2) {
for(int i = 3; i <= n; i++) {
dp[i] = (dp[i - 1] + dp[i - 2]) % 10007; //왜 여기서 10007을 나눠서 저장하는거지..?
}
return dp[n];
} else {
return dp[n];
}
}
static long topDown(int n) {
if(n < 3) {
return dp[n];
} else if(dp[n] > 0) {
return dp[n];
}
dp[n] = (topDown(n - 1) + topDown(n - 2)) % 10007;
return dp[n];
}
}
반응형