티스토리 뷰
안녕하세요, 감자코딩에 감자개발자입니다.
이번에 살펴볼 알고리즘 문제는 백준 알고리즘 2*n 타일링 1에 이어서 11726번 2*n 타일링2 문제입니다.
저번에 2*n 타일링문제를 잘 풀어보셨다면, 이 문제 또한 수월하게 푸실 수 있을것입니다.
문제부터 살펴보죠.
문제 링크
https://www.acmicpc.net/problem/11727
1. 문제
2×n 타일링 2 성공
시간 제한 메모리 제한 제출 정답 맞은 사람 정답 비율
1 초 256 MB 15559 9176 7458 59.436%
문제
2×n 직사각형을 2×1과 2×2 타일로 채우는 방법의 수를 구하는 프로그램을 작성하시오.
아래 그림은 2×17 직사각형을 채운 한가지 예이다.
입력
첫째 줄에 n이 주어진다. (1 ≤ n ≤ 1,000)
출력
첫째 줄에 2×n 크기의 직사각형을 채우는 방법의 수를 10,007로 나눈 나머지를 출력한다.
예제 입력 1
2
예제 출력 1
3
예제 입력 2
8
예제 출력 2
171
예제 입력 3
12
예제 출력 3
2731
2. 문제 해결 방법
1) 2*N 타일링을 만들어 2*1 , 2*1 ,2*2 타일링으로 채워나가는 경우의 수를 찾는 문제입니다.
2) 각각의 2*1 타일 , 2*1 타일, 2*2 타일에 경우의 수를 찾아보도록 하죠.
아래의 그림을 보시면 이해가 빠르실 것입니다.
(왼쪽), (가운데), (오른쪽)순으로 살펴보겠습니다.
DP = 2*N 이라는 사실과 최소의 도형의 개수를 생각하여야 합니다.
(왼쪽의 경우)
2*2 타일로 한번 채운 경우입니다.
(가운데의 경우)
1*2 타일로 두번 채운 경우입니다.
여기서 왜 두개를 채우냐고 생각하시는분이 있으실텐데 정확하게 n-2개만큼 처리해주기 위함입니다.
(오른쪽의 경우)
2*1 타일로 한번 채운경우입니다.
그러면 이제, 총 3개의 타일을 이용하여서 2*N타일의 경우의 수를 찾아내면 되겠지요?
즉, 위의 그림을 보게 되면 왼쪽과 가운데의 점화식은 N-2가 되게 되는데 동일하다는 것을 발견하셨죠? 그러면 결국 2 * (N - 2)개의 경우의 수를 따져주게 되면 된답니다.
그리고, 오른쪽의 점화식은 N-1이 성립하는것을 알 수 있습니다.
이것을 DP로 문제를 풀게 된다면 이전의 2*N타일링 문제와 거의 유사한 문제가 되겠죠?
하지만 주의할 것은, N의 값이 1일 경우와 N의 값이 2일 경우에 리턴받는값이 달라진다는것 입니다.
이것이 무슨 말인지 이해가 안가시는분도 있을겁니다.
- N = 1일 경우
2 * 1 의 타일링
|
|
- N = 2일 경우
2*2의 타일링
|
|
|
|
이 생성 됩니다. 그러면 우리가 가진 타일링의 종류는 총 3가지죠(2*1 ,2*1, 2*2) 타일입니다.
따라서, N=1 일 경우 총 2*1의 타일의 경우의 수 1개만 존재하게 되겠죠?
|
|
그리고 N=2 일 경우 총 (2*1, 1*2, 2*2) 타일이 존재 하므로, 총 3가지 경우를 리턴해주면 됩니다.
(2*1)
|
|
(1*2)
|
|
(2*2)
|
|
|
|
이해가 가시나요? 그러면 이제 소스코드를 작성해봅시다.
이해가 안가시는 분들은
[알고리즘] 백준 11726번 2*n 타일링 문제 DP
여기를 참고하시고 오시면 되겠습니다.
3. 코드 리뷰
//
// 2*n타일링2.cpp
// beakjoon_algorithm
//
// Created by kgh on 13/04/2019.
// Copyright © 2019 kgh. All rights reserved.
//
#include <stdio.h>
#include <iostream>
using namespace std;
int dp[1001];
int recursive(int n){
// N == 1 한가지 경우 2*1
if(n == 1){
return 1;
}
// N == 2 1*2 , 2*1 , 2*2 3가지 경우 리턴
if(n == 2){
return 3;
}
// 값 존재시 dp[n] 리턴 메모이 제이션
if(dp[n] > 0){
return dp[n];
}
// 아까 구한 점화식 적용
dp[n] = (recursive(n-1) + (2* recursive(n-2))) % 10007;
return dp[n];
}
int main(void){
int n;
cin >> n;
// 최종 경우의 수 출력
int result = recursive(n);
cout << result;
return 0;
}
2*N타일링 1 문제에 이어서 2*N타일링2 문제 까지 살펴보게되었습니다.
알고리즘을 평소에 많이 해놓으셔야지 저 처럼 인턴 시기에 힘들지 않습니다 D:
이상 감자코딩에 감자 개발자였습니다.
잘못된 부분이 있다면 의견 남겨주시면 감사하겠습니다 :)
'Algorithm' 카테고리의 다른 글
[알고리즘] 백준 카드구매하기 11052 DP 최댓값 (0) | 2019.04.13 |
---|---|
[알고리즘] 백준 9095번 1,2,3 더하기 DP (0) | 2019.04.13 |
[알고리즘] 백준 11726번 2*n 타일링 문제 DP (1) | 2019.04.12 |
[알고리즘] 백준 알고리즘 1463 1로만들기 DP - 시간복잡도 분석 (1) | 2019.04.12 |
[알고리즘] 백준 11724 연결 요소(DFS) (0) | 2019.04.11 |
- Total
- Today
- Yesterday
- node
- Spring
- Android
- 학교
- C langauge
- db
- 복습
- BFS
- 머신러닝
- 노드
- 알고리즘
- 스프링
- TensorFlow
- Controller
- 개발하는 관광이
- MVC
- 감자개발자
- 감자코딩
- 백준알고리즘
- 안드로이드
- 초보자를 위한 C언어 300제
- Algorigm
- 텐서플로우
- 리버싱
- 백준
- node.js
- C언어
- 코드엔진
- 프로그래밍
- programming
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |