끈기 있는 개발 공간
[Algorithm] 프로그래머스 - 아방가르드 타일링 본문
https://school.programmers.co.kr/learn/courses/30/lessons/181186
접근
여러 경우의 수를 고려해야 하는 DP 문제다.
규칙성을 찾기 위해서는 $n$ 이 증가함에 따라 새로 추가되는 영역을 봐야 한다.
일단 문제에서도 확인할 수 있듯이 $n=3$ 인 경우의 수는 10이다.
여기서 $n=4$ 에서 재사용할 수 있는 경우는 90도 회전된 $3\times{1}$ 타일이 있는 경우다.
나머지 $3\times{1}$ 타일이 있는 경우는 $n=1$ 에서의 결과를 재사용하고, ㄱ자 타일로만 구성된 $3\times{2}$ 타일에서는 $n=2$ 에서의 결과를 재사용해야 하기 때문이다.
다음으로 $n=4$ 에서 재사용 가능한 경우는 다음과 같이 두 개다.
90도 회전된 $3\times{1}$ 타일로 가로를 꽉 채우도록 타일링하는 데 초점을 두면 이러한 경우를 쉽게 찾을 수 있다.
$n=5$ 일 때는 다음과 같이 두 개다.
$n=6$ 일 때는 다음과 같이 네 개다.
$n=7$ 일 때는 다음과 같이 두 개다.
다음은 $n=8$ 일 때와 $n=9$ 일 때의 경우 중 한 개씩만 나타낸 그림이다.
한 개씩만 나타낸 이유를 설명하겠다.
눈치챘을 수도 있을 것이다. $n$ 이 7 이상일 때부터는 90도 회전된 $3\times{1}$ 타일 세 개가 연속으로 쌓아진 형태가 계속 추가되기 때문에 비슷한 형태가 반복된다.
예를 들어 다음과 같이 $n=7$ 일 때의 하나의 경우는 $n=4$ 일 때의 경우에서 90도 회전된 $3\times{1}$ 타일 세 개가 연속으로 쌓아진 형태가 추가되는 식이다.
$n=8$ 과 $n=9$ 일 때도 마찬가지다.
그래서 점화식은 다음과 같이 세울 수 있다.
$dp[i]=dp[i-1]+2\times{dp[i-2]}+5\times{dp[i-3]}+2\times{dp[i-4]}+2\times{dp[i-5]}+4\times{dp[i-6]}+2\times{dp[i-7]}+2\times{dp[i-8]}+4\times{dp[i-9]}...$
이를 구현하기 위해서는 누적합을 저장해서 계산해도 되지만 다음과 같이 식을 간소화할 수도 있다.
$dp[i] - dp[i-3] = dp[i-1]+2\times{dp[i-2]}+5\times{dp[i-3]}+dp[i-4]-dp[i-6]$
$dp[i] = dp[i-1]+2\times{dp[i-2]}+6\times{dp[i-3]}+dp[i-4]-dp[i-6]$
그리고 문제에서 나머지 연산을 필요로 하는데,
자바에서는 뺄셈에서 모듈러 연산 시 음수를 배제하기 위해 다음 식을 적용한다.
$(A-B)\mod{M}=((A\mod{M})-(B\mod{M})+B)\mod{M}$
이와 관련해 포스팅을 한 적이 있다. 궁금하면 다음 글을 참고하자.
소스코드(Java)
class Solution {
static final int MOD = 1000000007;
public long solution(int n) {
long[] dp = new long[100001];
dp[0] = 1;
dp[1] = 1;
dp[2] = 3;
dp[3] = 10;
dp[4] = 23;
dp[5] = 62;
dp[6] = 170;
//dp[12] = dp[11] + 2*dp[10] + 5*dp[9] + 2*(dp[8]+dp[5]+dp[2]) + 2*(dp[7]+dp[4]+dp[1]) + 4*(dp[6]+dp[3]+dp[0]);
//dp[9] = dp[8] + 2*dp[7] + 5*dp[6] + 2*(dp[5]+dp[2]) + 2*(dp[4]+dp[1]) + 4*(dp[3]+dp[0]);
//dp[12] - dp[9] = dp[11] + 2*dp[10] + 5*dp[9] + dp[8] - dp[6];
//dp[12] = dp[11] + 2*dp[10] + 6*dp[9] + dp[8] - dp[6];
for(int i = 7; i <= n; i++) {
dp[i] = (dp[i-1] + (2*dp[i-2]) % MOD + (6*dp[i-3]) % MOD + dp[i-4] - dp[i-6] + MOD) % MOD;
}
return (int)dp[n] % MOD;
}
}'Algorithm' 카테고리의 다른 글
| [Algorithm] 프로그래머스 - 인사고과 (0) | 2024.08.27 |
|---|---|
| [Algorithm] 프로그래머스 - 연속 펄스 부분 수열의 합 (0) | 2024.08.26 |
| [Algorithm] 프로그래머스 - 상담원 인원 (0) | 2024.08.25 |
| [Algorithm] 프로그래머스 - 에어컨 (0) | 2024.08.22 |
| [Algorithm] 프로그래머스 - 산 모양 타일링 (0) | 2024.08.22 |