본문 바로가기

백준/DP

백준 32250 - Super Shy (Easy)

728x90

https://www.acmicpc.net/problem/32250

힌트 1

더보기

만약 먼저 앉은 사람이 아무도 없을 경우 아무 자리에나 앉을 수 있다.

 

이 조건이 대단히 중요하다.

힌트 2

더보기

최초로 사람을 배치한 이후, 규칙에 따라 사람을 배치하는데 나타나는 성질을 찾을 수 있는가?

풀이

더보기

먼저 사람을 아무 곳에 배치한다고 해보자.

 

그러면 그 사람을 기준으로 나눈 왼쪽 구간과 오른쪽 구간 $L$과 $R$을 얻을 수 있다.

 

$L$과 $R$에서 사람을 배치할 때는 문제의 규칙에 의해 다음과 같은 성질을 발견할 수 있다.

 

구간 $L, R$에서 첫 번째 사람이 놓인 기준점을 포함하여 각 사람과의 거리는 2 또는 3이다.

 

이는 거리를 가능한한 멀리 떨어트려야 한다는 조건을 만족시키기 위해 중앙에 배치하면서 다시 두 개의 구간으로 나뉘는 것이 반복되어 최종적으로는 거리가 2 또는 3을 유지하며 배치하기 때문이다. (1은 인접하게 되므로 불가하다.)

 

 

따라서 우리는 다음 함수를 정의할 수 있다.

 

$g(x) := $ 최초로 사람이 배치되서 나눠진 구간의 길이가 $x$일 때 규칙에 따라 배치할 수 있는 사람의 수

 

이 때 $g(x)$는 규칙에 따라 사람을 중간 지점에 배치 후 다시 둘로 나누는 과정을 통해 길이가 2 또는 3이 될 때까지 쪼개도록 할 수 있다.

 

$g(x)$를 구하는 과정에서 중복되는 계산이 발생하므로 동적 계획법을 사용하여 효율적으로 계산할 수 있다.

 

최초로 배치하는 위치에 따라 답이 달라질 수 있으므로 1부터 $N$까지 배치해보며 $MAX(1 + g(L) + g(R))$을 구하면 된다.

 

시간 복잡도: $O(N \log N)$

 

정답 코드 - pypy3

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
32
33
34
35
36
37
38
39
import sys
 
dp = dict()
 
def g(x: int):
    if x <= 1:
        return 0
    if x <= 3:
        return 1
    if x in dp:
        return dp[x]
 
    l = x // 2
    r = x - l
    val = g(l) + g(r)
    dp[x] = val
    return dp[x]
 
 
def solve():
    n = int(input())
    ans = -10000009
    for i in range(1, n + 1):
        val = 1
        l = i - 1
        r = n - i
 
        if l > 0:
            val += g(l)
        if r > 0:
            val += g(r)
 
        if ans < val:
            ans = val
    print(ans)
 
if __name__ == "__main__":
    sys.setrecursionlimit(1000)
    solve()
cs

 

 

728x90

'백준 > DP' 카테고리의 다른 글

백준 12199 - Password Attacker (Large)  (1) 2024.11.19
백준 23280 - 엔토피아의 기억 강화  (1) 2024.11.17
백준 1398 - 동전 문제  (1) 2024.04.25
백준 2040 - 수 게임  (3) 2022.09.28
백준 24457 - 카페인 중독  (0) 2022.08.25