가로 길이가 n으로 주어질 때, 가능한 경우의 수는 몇개인가? 를 구하는 문제이다.
예를 들어 n이 3이라고 가정해보자.
이런 3개의 경우의 수가 가능할 것이다.
n개일 때는 경우의 수가 몇개인지를 구하려면 어떻게 해야할까?
문제 풀이
이 문제는 기본적인 DP문제이다. 사실 DP문제는 어떠한 알고리즘이 있다기보단, 창의력이나 사고력을 요하는 경우가 더 많은 것 같다. 하지만, 자주 나오는 유형들을 보면 대부분 점화식을 이용하여 다음 항을 유추하는 케이스와 완전탐색과 함께 사용하는 케이스가 가장 많은 것 같다. 자주 풀어보면 감이 올 것이다.
이 문제는 먼저 점화식을 세워야 한다.
먼저, n개의 타일을 배치하는 여러 개의 경우의 수가 있다고 했을 때 모든 경우의 수를 고려하는 것이 아니라 딱 2개의 경우로만 나눠보자.
크게 두 개의 경우로 나누어 보자.
1. 맨 앞의 블럭이 서있는 경우
2. 맨 앞의 블럭이 누워있는 경우
맨 앞의 블럭이 서있는 경우와 맨 앞의 블럭이 누워있는 경우중 서로 겹치는 경우가 있을까?
절대 없을 것이다. 앞의 블럭 모양이 다르기 때문이다.
그렇기 때문에, N개의 줄에 타일을 배치하는 경우의 수는 맨 앞의 타일 이 서있는 경우 + 맨 앞의 타일 이 누워있는 경우로 바꿔서 생각해볼 수 있다.
N개의 줄에 타일을 배치하는 경우의 수 = 맨 앞의 타일이 서있는 경우 + 맨 앞의 타일 이 누워있는 경우
그렇다면, 두 개의 경우를 하나씩 살펴보자.
맨 앞의 타일 이 서있는 경우라면, 맨 앞의 타일 은 고정이기 때문에 뒤의 N-1줄에 타일을 배치하는 경우의 수가
곧 타일을 배치하는 전체 경우의 수이다.
즉 맨 앞의 타일 이 서있는 경우의 수는 N-1줄에 타일 을 배치하는 경우의 수이다.
N개의 줄에서 맨 앞의 블럭이 서있는 경우의 수 = N-1 줄에 타일을 배치하는 경우의 수
이번엔, 두 번째 경우를 보자.
맨 앞의 타일이 누워있는 경우이다. 타일이 누워있다면 총 두 줄을 점유하기 때문에, 뒤의 N-2줄에 타일을 배치하는 경우가 곧 타일을 배치하는 경우의 수가 된다.
N개의 줄에서 맨 앞의 블럭이 누워있는 경우의 수 = N-2 줄에 타일을 배치하는 경우의 수
이제, 맨 위에서 처음으로 구했던 명제를 보자.
N개의 줄에 타일을 배치하는 경우의 수
= 맨 앞의 타일이 서있는 경우 + 맨 앞의 타일 이 누워있는 경우
= N-1 줄에 타일을 배치하는 경우의 수 + N-2 줄에 타일을 배치하는 경우의 수
이런 결론에 도달할 수 있다.
우리는 직접 계산을 통해, N이 1, 2, 3 일 때의 경우의 수는 쉽게 구할 수 있다.
D(N) 이 N개의 줄에 타일을 배치하는 경우의 수라면,
D(1) = 1;
D(2) = 2;
D(3) = 3;
이렇게 될 것이다.
이제부터 반복문을 돌며 값을 구하면 된다.
D(4) = D(3) + D(2)
D(5) = D(4) + D(3)
.
.
.
.
D(N) = D(N - 1) + D(N - 2) 까지 답을 구하면 문제는 끝난다.
풀이 코드
#include <string>
#include <vector>
using namespace std;
int solution(int n)
{
std::vector<int> DP(n + 1, 0);
DP[1] = 1;
DP[2] = 2;
DP[3] = 3;
int CurIndex = 4;
int EndINdex = n;
while(CurIndex <= n)
{
DP[CurIndex] = (DP[CurIndex - 1] + DP[CurIndex - 2]) % 1000000007;
CurIndex++;
}
return DP[n];
}
풀이는 정말 간단하다.
위에서 구했던 점화식을 그대로 코드로 작성하면 된다.
코드를 짜는게 어렵다기보단, 아이디어를 떠올리는게 다소 어려울 수 있었던 문제이다.
결과
'코딩테스트 문제 풀이 (C++)' 카테고리의 다른 글
백준 16493 - 최대 페이지 수 (C++) (1) | 2024.04.02 |
---|---|
백준 1890 - 점프 (C++) (0) | 2024.04.02 |
프로그래머스 - 피로도 (C++) (0) | 2024.04.01 |
백준 11501 - 주식 (C++) (1) | 2024.03.31 |
백준 11404 - 플로이드 (C++) (0) | 2024.03.30 |