https://www.acmicpc.net/problem/1146
브루트 포스나 BFS 의 식으로도 풀 수 있지만 시간제한에 걸리게 됩니다.
다른 방법을 찾아봅시다.
우리는 N 명의 학생을 줄세워야 합니다.
그 중 번호가 가장 큰 N 번째 학생을 P 번째 순서에 줄 세우는 경우를 생각해보겠습니다.
그럼 남은 N-1 명의 학생을 줄 세워야 하는데, 어차피 수의 대소만이 중요하기 때문에 지그재그 패턴만 맞으면 어떤 학생이 어디에 서던 중요하지 않습니다.
즉 N 번째 학생을 P 번째 세우고 양 옆에 남은 학생들을 다시 줄세우는 작은 단계로 쪼갤 수 있습니다.
즉 이 문제를 DP 로 풀 수 있습니다.
N 명의 학생 중 P 번째 자리에 N 번째 학생을 줄세운다고 생각하겠습니다.
해당 경우를 A_NP 라고 부르겠습니다.
P 가 1 인 경우 == N 번째 학생이 첫 번째 자리에 서 있을 경우
남아있는 번호는 모두 N 보다 작으므로 지그재그 패턴은
N - (작은수 - 큰수 - 작은수 - ... ) 의 패턴을 띄게 됩니다.
즉 경우의 수는 N-1 명의 학생을 지그재그로 줄세우는 경우의 수와 같습니다.
N-1 명의 학생을 지그재그로 줄세우는 경우의 수는 N-1 번 학생을 모든 자리에 세워본 경우의 수의 합과 같으므로
A_N1 = ∑(P = 1~N) (A_(N-1)(P)) 입니다.
P 가 2 인 경우 == N 번째 학생이 두 번째 자리에 서 있을 경우
역시 남아있는 번호는 모두 N 보다 작으므로 지그재그 패턴은
(작은수) - N - (작은수 - 큰수 - ...) 의 패턴을 띄게 됩니다.
즉 경우의 수는 N-1 명의 학생 중 왼쪽에 설 한명을 정하는 경우의 수에
N-2 명의 학생을 지그재그로 줄세우는 경우의 수를 곱한 값과 같습니다.
A_N2 = (N-1)_C_(1) * ∑(P = 1~(N-2)) (A_(N-2)(P))
...
P 가 K 인 경우 == N 번째 학생이 K 번째 자리에 서 있을 경우
(... - 작은수) - N - (작은수 - ...) 의 패턴을 띄게 됩니다.
즉 경우의 수는 N-1 명의 학생 중 왼쪽에 설 K-1 명을 정하는 경우의 수에
K-1 명을 지그재그로 줄 세우는 경우의 수
N-K 명을 지그재그로 줄 세우는 경우의 수를 곱한 값과 같습니다.
A_NK = (N-1)_C_(K-1) * ∑(P = 1~(K-1)) (A_(K-1)(P)) * ∑(P = 1~(N-K)) (A_(N-K)(P))
코드로 써보자면
memo[N][P] = N 명의 학생중 P 번째 자리에 N 번째 학생을 위치시킬 때 경우의 수
memo[N][P] = (N-1)_C_(P-1) * sum(memo[P-1]) * sum(memo[N-P]) 가 됩니다.
하지만 고려할 경우가 더 있습니다.
일반적으로 양 끝의 수열은 지그재그의 형태가 정해져 있지 않습니다.
즉 큰수 - 작은수 - 큰수 - ... 일수도 있고 작은수 - 큰수 - 작은수 - ... 일 수도 있습니다.
하지만 가장 큰 수를 고정시키는 방식이었기 때문에 양쪽에 오는 수열은 형태가 고정됩니다.
즉 전체 지그재그 수열을 2 로 나눈 뒤 계산해야 합니다.
다만 P == 1 / P == 2 / P == N-1 / P == N 일 경우
한쪽 수열에 속해있는 숫자의 수가 0 / 1 이므로 수열의 형태는 하나밖에 없습니다.
즉 이 경우에는 해당하는 쪽의 수열은 2로 나누어주지 않아도 됩니다.
물론 양쪽 다 해당할 경우 양쪽 모두 나누어주지 않습니다.
'Coding Test > BaekJoon_Python' 카테고리의 다른 글
백준 1229 <육각수> Python (1) | 2024.09.22 |
---|---|
백준 1174 <줄어드는 수> Python (0) | 2024.09.21 |
백준 1153 <네 개의 소수> Python (1) | 2024.09.19 |
백준 1106 <호텔> Python (1) | 2024.09.15 |
백준 22021 <자동분무기> Python (0) | 2024.09.15 |