https://www.acmicpc.net/problem/1309
1309번: 동물원
첫째 줄에 우리의 크기 N(1≤N≤100,000)이 주어진다.
www.acmicpc.net
[문제 요약]
- 어떤 동물원에 가로로 두칸 세로로 N칸인 아래와 같은 우리가 있다.
- 이 동물원에는 사자들이 살고 있는데 사자들을 우리에 가둘 때, 가로로도 세로로도 붙어 있게 배치할 수는 없다.
- 이때 2 * N 배열에 사자를 배치하는 경우의 수를 구하여라.
- 사자를 한 마리도 배치하지 않는 경우도 하나의 경우의 수로 친다고 가정한다.
- 정답은 9901로 나눈 나머지를 출력하라.
[문제 조건]
- 첫째 줄에 우리의 크기 N(1≤N≤100,000)이 주어진다.
- 시간 제한 : 2초
- 메모리 제한 : 128MB
[문제 풀이]
문제에서 정답을 어떤 수로 나눈 나머지를 출력하라는 건 정답이 매우 크다는 걸 의미한다. 벌써부터 쫄린다.
문제를 읽어보고 한 번 생각을 해보면 딱히 떠오르는 방법이 DP말고는 떠오르지 않는다.
그래서 필자는 DP를 이용하여 문제를 접근하였다.
먼저 가로줄 한 줄에 배치할 수 있는 경우는 총 3가지이다. 왼쪽에 놓거나, 오른쪽에 놓거나 아니면 배치하지 않거나.
여기서 필자는 두 가지 경우의 수로 나누어 생각해봤다. 배치하지 않았을 때와 배치를 하나라도 했을 경우.
이 방법을 적용하여 표를 그리고 값들을 작성하면 아래와 같다.
일단, 예들들어 초록색 부분이 의미하는 건 N=2일때 2번째 칸에 사자를 배치하지 않았을때 경우의수는 총 3가지, 둘 중 한곳이라도 배치한다면 4가지 해서 총 7가지라는 의미이다.
여기서 표를 채우는 방법은 간단하다.
만약 N번째에 사자를 채우지 않는다는 것은 크기가 2 * (N-1)배열에 사자를 배치하는 경우의 수와 같을 것이다. 왜냐하면 배치하지 않는건 다른 제약을 받지 않으니.
그리고 N번째에 배치한다고 생각하면, 왼쪽 오른쪽 총 2가지 경우가 있다. 그리고 만약 N-1번째에 배치 하지 않았다면 왼쪽 오른쪽 둘 다 가능함으로 7x2 = 14.
그 다음 N-1번째에 사자가 배치되어 있을 경우 N-1번째에 따라서 N번째에 배치할 수 있음으로 N번째는 N-1번째에 따라가게 된다. 따라서 10개 추가 하면 10+14해서 총 24가지가 나온다.
정리하자면
DP[N][0] = DP[N-1][0] + DP[N-1][1]
DP[N][1] = DP[N-1][0] * 2 + DP[N-1][1]
해서 DP[N][0] + DP[N][1]이 정답이 될 것이다.
근데 식을 가만히 보고있자니 뭔가 정리를 할 수 있을 것 같다. MP[N]을 2 * N에 사자를 배치하는 수라고 다시 정의하면
DP[N][0] + DP[N][1] = 3 * DP[N-1][0] + 2 * DP[N-1][1]
MP[N] = 2*MP[N-1] + MP[N-2]이다. ( 남은 DP[N-1][0]은 사실상 N-2일때의 값과 같긴 때문에 MP[N-2]로 표현 가능)
그래서 사실상 이 문제의 점화식은 MP[N] = 2*MP[N-1] + MP[N-2] 가 된다.
그리고 자료형을 unsigned long long과 값을 9901의 나머지로 저장을 해주면 정답이 된다.
[소스 코드]
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cmath>
#include <deque>
#include <list>
#include <math.h>
#include <map>
#include <queue>
#include <stack>
using namespace std;
int N;
vector<unsigned long long> DP;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cout.tie(NULL);
cin >> N;
DP.resize(N + 1);
DP[0] = 3;
DP[1] = 7;
for (int i = 2; i <= N; i++)
{
DP[i] = (2 * DP[i - 1])%9901 + (DP[i - 2]%9901) % 9901;
}
cout << DP[N-1] % 9901;
}

굳
'BOJ 풀이' 카테고리의 다른 글
[BOJ/백준 11561/C++] 징검다리 (2) | 2022.12.17 |
---|---|
[BOJ/백준 1446/C++] 지름길 (1) | 2022.12.15 |
[BOJ/백준 1976/C++] 여행 가자 (0) | 2022.12.14 |
[BOJ/백준 16235/C++] 나무 재테크 (0) | 2022.12.13 |
[BOJ/백준 15684/C++] 사다리 조작 (0) | 2022.12.12 |