λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
πŸƒ algorithm/boj

BOJ 4811 - μ•Œμ•½

by HandHand 2021. 6. 7.

문제

λ°±μ€€ 온라인 저지 - 4811번

풀이 κ³Όμ •

μ•Œμ•½μ„ ν•˜λ‚˜ 전체λ₯Ό λ¨Ήκ±°λ‚˜ 반개λ₯Ό λ¨Ήμ–΄μ„œ λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  λ¬Έμžμ—΄μ˜ 개수λ₯Ό μ°ΎλŠ” λ¬Έμ œμž…λ‹ˆλ‹€.

μ™„μ „νƒμƒ‰μœΌλ‘œ μ ‘κ·Όν•˜λ©΄ 경우의 μˆ˜κ°€ λ„ˆλ¬΄ 많기 λ•Œλ¬Έμ— μ€‘λ³΅λœ 연산을 많이 μˆ˜ν–‰ν•˜κ²Œ λ©λ‹ˆλ‹€.

λŒ€μ‹  동적 κ³„νšλ²• 을 ν™œμš©ν•΄μ„œ λͺ¨λ“  경우의 수λ₯Ό κ΅¬ν•˜λ©΄ μ€‘λ³΅λœ 연산을 많이 쀄일 수 μžˆμŠ΅λ‹ˆλ‹€.

dp[i][w][h] = μ•Œμ•½ ν•œκ°œκ°€ W개, λ°˜κ°œκ°€ h개 μžˆμ„ λ•Œ i λ‚ λΆ€ν„° μ‹œμž‘ν•΄μ„œ λ§Œλ“€ 수 μžˆλŠ” λͺ¨λ“  λ¬Έμžμ—΄μ˜ 개수 라고 μ •μ˜ν•œλ‹€λ©΄

λ‹€μŒκ³Ό 같은 점화식을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

dp[i][w][h] = dp[i + 1][w][h + 1] + dp[i + 1][w + 1][h]


단 μ „μžμ˜ 경우 `h < w` μ—¬μ•Ό ν•˜λ©° ν›„μžμ˜ κ²½μš°λŠ” `w < N(전체 μ•Œμ•½ 수)` 이어야 ν•©λ‹ˆλ‹€.

μ½”λ“œ


import sys

N = 0
memo = []


def eat_pill(day, w, h):
    if day == 2 * N - 1:
        return 1

    if memo[day][w][h] != -1:
        return memo[day][w][h]

    memo[day][w][h] = 0

    # μ•Œμ•½ 반개 λ¨ΉκΈ°
    if h < w:
        memo[day][w][h] += eat_pill(day + 1, w, h + 1)

    # μ•Œμ•½ ν•œκ°œ λ¨ΉκΈ°
    if w < N:
        memo[day][w][h] += eat_pill(day + 1, w + 1, h)

    return memo[day][w][h]


def solution():
    global memo

    memo = [[[-1] * (N + 1) for _ in range(N + 1)] for _ in range(2 * N)]
    return eat_pill(0, 1, 0)


if __name__ == '__main__':
    while True:
        N = int(sys.stdin.readline())
        if N == 0:
            break

        answer = solution()
        print(answer)
λ°˜μ‘ν˜•

πŸ’¬ λŒ“κΈ€