Problem Solving/Else

BOJ 5626 : 제단

PS리버싱마크해커박종휘TV 2022. 5. 5. 15:24

5626번: 제단 (acmicpc.net)

 

5626번: 제단

첫째 줄에 가능한 제단의 수를 1,000,000,007로 나눈 나머지를 출력한다.

www.acmicpc.net

 

 

시간 복잡도:

  • O(N * H/2)

 

알고리즘:

  • DP

 

 

 

 

 

말이 꼬여있어서 어렵습니다. 하지만 보면, i번째 제단과 i-1번째 제단 혹은 i+1번째 제단의 차이는 1 이상 날 수 없습니다. 이는 계단 수 문제랑 비슷한데, 변형되었습니다. 조건은 다음과 같습니다.

 

  • 시작은 0이여야 합니다. 따라서 1번째 제단의 입력이 0 혹은 -1이 아니라면, 바로 0을 출력합니다.
  • 끝 또한 0이여야 합니다.
  • i번째 제단이 -1이 아닌 경우 i 빼고 모든 값을 0으로 초기화합니다.
  • i번째 제단을 j로 설치하는 경우의 수는 i-1번째를 j, j+1, j-1로 설치하는 경우의 수의 합과 같습니다.

 

여기서 우리는 이 문제가 DP인 것을 손쉽게 알 수 있습니다.

 

하지만 문제가 있습니다. N이 10,000 이고 H의 최댓값 또한 10,000 입니다. 하지만 보듯이, i - 1번째의 값만 알고 있으면 되니, 굳이 2차원으로 만들 필요가 없습니다. 또한, H도 실질적인 최댓값 5,000을 벗어날 수 없습니다. 따라서 우리는 dp 배열을 1차원으로 해서 풀 수 있습니다. (사실 2차원으로 해도 메모리 초과가 안 납니다.)

 

더보기
#include <iostream>

using namespace std;
#define int long long
#define MOD 1000000007
#define H 5001

int N, arr[10001], dp[5003][2];

signed main() {
	
	ios_base::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);

	cin >> N;
	for (int i = 1; i <= N; i++) {
		cin >> arr[i];
	}

	if (arr[1] >= 1) { cout << "0" << '\n'; return 0; }
	dp[0][0] = 1; int ptr = 0;
	for (int i = 2; i <= N; i++) {
		for (int j = 0; j <= H; j++) {
			dp[j][!ptr] = 0;
			if (j != 0) dp[j][!ptr] += dp[j - 1][ptr];
			dp[j][!ptr] += dp[j][ptr] + dp[j + 1][ptr];
			dp[j][!ptr] %= MOD;
			if (arr[i] != j && arr[i] != -1) dp[j][!ptr] = 0;
		}
		ptr = 1 - ptr;
	}

	cout << dp[0][ptr] << '\n';
}

 

'Problem Solving > Else' 카테고리의 다른 글

BOJ Diamond V  (2) 2024.06.10
BOJ 18251 : 제목 생략  (0) 2022.04.25
Problem Solving @ 2022/04/23  (0) 2022.04.23
BOJ 13907 : 세금  (0) 2022.04.22
Problem Solving @ 2022/04/21  (0) 2022.04.21