https://www.acmicpc.net/problem/11727
설명 :
다이나믹 프로그래밍에의 기본 문제중에 기본 문제인 타일링 문제이다.
특정 모양의 타일들로 직사각형을 채울 수 있는 가짓수를 구한다.
다이나믹 프로그래밍을 할 때 가장 중요한 것은 memoization 과 점화식(순환식)이다.
순환식을 먼저 만들어보자.
f(n) 이라는 가상의 함수가 있는데,
이 함수는 2xn 크기의 직사각형을, 주어진 타일들의 개수로 채우는 가짓수를 반환한다.
문제에서 주어진 타일은 2x1, 2x2 두 개의 타일이다.
이 두 개의 타일로 2xn 마지막을 채우는 상상을 해보자.
위 그림의 설명대로 총 3가지 방법으로 마지막 타일이 채워지게 될 것이다.
그렇다면 아래와 같은 식을 하나 만들 수 있겠다.
f(n) = f(n-1) // 2x1 타일 하나로 채우는 경우. 1칸을 채웠음으로 남은 n-1 칸을 채우는 가짓수를 구하면 됨 +f(n-2) // 2x2 타일 하나로 채우는 경우. 2칸을 채웠음으로 남은 n-2 칸을 채우는 가짓수를 구하면 됨. +f(n-2) // 2x1 타일 둘로 채우는 경우. 2칸을 채웠음으로 남은 n-2 칸을 채우는 가짓수를 구하면 됨. |
정리하면
f(n) = f(n-1) + 2*f(n-2) |
가 된다. 이것이 이 문제의 점화식 되시겠다.
이 점화식이 계속 실행된다면 처음에 어떻게 채우느냐가 또 관건이 되는데,
그건 base case 로 우리가 직접 정해줘야 한다.
즉,
f(0) 은 방법이 없으므로 f(0) = 0
f(1) 은 2x1 타일 하나로 채우는 경우 밖에 없으므로 f(1) = 1
f(2) 는 2x1 타일 두 개로 채우는 방법이 둘, 2x2 타일 하나로 채우는 방법이 하나, 총 세 가지가 있으므로 f(2) = 3
이 base case 를 염두해두고 코드를 작성하면 된다.
memoization 을 위해 n 크기만큼의 array 하나를 준비한 다음,
bottom up 방식을 좇아 i=1 부터 i=n 이 될 때까지 차근차근 위의 식 대로 올라가면 된다.
마지막에 반환하는 값은, 우리가 알고싶은 "2xn 크기의 직사각형을, 주어진 타일들의 개수로 채우는 가짓수" 이므로
f(n) 을 반환한다.
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
int m[] = new int[n+1];
for(int i=1; i<=n; i++){
if(i<2) m[i]=i;
else if(i==2) m[i]=3;
else m[i]=m[i-1]+2*m[i-2];
m[i]%=10007;
}
System.out.println(m[n]);
}
}
코드 : http://boj.kr/5fcb93cdaa174a98b5d00bc322dc8c5c
p.s
어떻게 식만 세우고 1부터 차근차근 올라간 것이 우리가 원하는 값이 되는가?
재귀식을 이용한 다이나믹 프로그래밍을 생각해보면,
결국에 재귀식 자체도 똑같은 식을 사용한다고 할 때
가장 아래서부터 하나씩 값을 반환해가면서 순차적으로 n을 향해 쌓여가는 과정을 거친다.
똑같은 식을 그냥 다르게 표현한 거라고 생각하자.
bottom up 방식이란, 작은 문제들을 미리 풀어두고
작은 문제들의 결과를 바탕으로 더 큰 문제들을 풀어나가는 것을 말 함
그래서 재귀 함수 대신 반복문을 사용함
내가 수강한 다이나믹 프로그래밍 강의
권오흠 교수님 수업 https://youtu.be/K15qLnKKrow
'Coding Interview' 카테고리의 다른 글
Longest Increasing Subsequence 알고리즘 (0) | 2020.02.02 |
---|---|
[Baekjoon] 2156번 포도주 시식 (0) | 2020.01.30 |
[Coding Interview] 비트 관련 문제 (0) | 2020.01.26 |
[Coding Interview] 트리 관련 문제 (0) | 2020.01.26 |
[JAVA] 같은 역할을 하지만 무거운 연산들 (0) | 2020.01.24 |