코딩 테스트 준비! (백준)/DP
[동적프로그래밍]백준 11726,11727번 2 x n 타일링 1,2) (C++)
lee-soo
2025. 3. 29. 18:01
https://www.acmicpc.net/problem/11726
해당 문제는 2 x N 타일안에 직사각형을 1 x 2 와 2 x 1로 채우는 경우의 수를 구하는 것이다.
예를들어 2 x 1의 경우 세로로 세워진 직사각형 하나만 들어가므로 1
2 x 2의 경우 둘다 누워있거나 둘다 서있는 직사각형만 들어가므로 2
이렇게 되는 것이다.
그렇다면, 이걸 어떻게 구해야 할까?
먼저 n번째 타일의 갯수를 구할 때, 맨 마지막에 채우는 타일이 저렇게 있다면 n-1의 값과 n의 값은 같은 것일것은 이해가 갈 것이다.
그렇다고 만약 모든 값이 같아지게 되면 당연히 답은 아닐것이다. 이때 생각해야 하는게 또 다른 경우의 수이다.
바로 이것이다. 이렇게 마지막에 채워지는 값에 대한 경우의수는 이것 2가지 밖에 없다.
2 x 2와 2 x 1인 것이다.
그렇다면 n의 값 = n-1의 값 + n-2의 값이므로
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n;
cin >> n;
int dp[n + 1];
dp[1] = 1;
// 2*1의 경우 1개
dp[2] = 2;
// 2*2 의 경우 2개
for (int i = 3; i < n + 1; i++)
{
dp[i] = dp[i - 1] + dp[i - 2];
dp[i] %= 10007; // 모듈러
}
cout << dp[n];
}
이런 식이 나오게 된다.
이걸 풀었다면 11727번을 매우 쉽게 풀 수 있을 것이다.
https://www.acmicpc.net/problem/11727
해당 문제는 앞선 경우의 수에서 단순히 2 x 2로도 채울 수 있는 경우가 생긴 것이다.
그렇다고해서 문제를 푸는 방식에 달라지는 것은 없다
이 경우의 수만 또 더해주면 된다
그렇게 되면
n-1 + n-2 + n-2가 되며
식으로 표현 시
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n;
cin >> n;
int dp[n];
dp[1] = 1;
dp[2] = 3;
for (int i = 3; i < n + 1; i++)
{
dp[i] = dp[i - 1] + dp[i - 2] * 2;
dp[i] %= 10007;
}
cout << dp[n];
}
이렇게 나온다.
dp의 기본적인 특징을 반드시 알아라 작은 해답으로써 큰 해답을 얻는것이 핵심이며,
처음 경우의 수는 단순하게라도 알아보는 것이 중요할 것이다.