λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°
μ½”λ”©ν…ŒμŠ€νŠΈ(Baekjoon)

[python] Baekjoon 1006 : 슡격자 초라기

by SeopπŸ˜€ 2024. 1. 21.
λ°˜μ‘ν˜•

문제 - Baekjoon 1006 : 슡격자 초라기

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

 

1006번: 슡격자 초라기

ν•˜λ‚˜μ˜ 특수 μ†ŒλŒ€λ‘œ μΈμ ‘ν•œ 두 μ˜μ—­μ„ 컀버할 수 μžˆλŠ” λ°°μΉ˜λŠ” (2,10), (9,16), (4,5), (7,8), (13,14) 이닀. 그리고 λ‚˜λ¨Έμ§€ 6개 ꡬ역은 각각 ν•˜λ‚˜μ˜ 특수 μ†ŒλŒ€λ‘œ 컀버할 수 μžˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ μ΅œμ†Œ 11개 특수 μ†Œ

www.acmicpc.net

핡심

"νŠΉμˆ˜μ†ŒλŒ€ μ΅œμ†Œ 배치 계산"

λ‚΄μš©

두 ν–‰μœΌλ‘œ κ΅¬μ„±λœ n개의 μ—΄λ‘œ 이루어져 있으며, 각 μΉΈμ—λŠ” 적의 μˆ˜κ°€ μ£Όμ–΄μ§‘λ‹ˆλ‹€. λͺ©ν‘œλŠ” μ£Όμ–΄μ§„ 쑰건 ν•˜μ—μ„œ 특수 μ†ŒλŒ€λ₯Ό λ°°μΉ˜ν•˜μ—¬ λͺ¨λ“  ꡬ역을 적절히 μ»€λ²„ν•˜λŠ” 데 ν•„μš”ν•œ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό κ³„μ‚°ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€. 특수 μ†ŒλŒ€λŠ” μΈμ ‘ν•œ 두 ꡬ역을 λ™μ‹œμ— 컀버할 수 있으며, ν•œ μ†ŒλŒ€κ°€ 컀버할 수 μžˆλŠ” 적의 총 μˆ˜λŠ” m을 μ΄ˆκ³Όν•  수 μ—†μŠ΅λ‹ˆλ‹€.

 

coding test

μ½”λ“œ

def solve(dp_state):
    # dp ν…Œμ΄λΈ” μ΄ˆκΈ°ν™”. 4κ°€μ§€ μƒνƒœλ₯Ό κ°–κ³ , 각 μƒνƒœλŠ” n+1의 길이λ₯Ό κ°–μŠ΅λ‹ˆλ‹€.
    dp = [[2 * n] * (n + 1) for _ in range(4)]
    dp[dp_state][-1] = 0  # μ„ νƒλœ μƒνƒœμ˜ λ§ˆμ§€λ§‰ ꡬ역을 0으둜 μ΄ˆκΈ°ν™”

    for index in range(n):
        for state in range(4):
            # 각 μƒνƒœμ— 따라 이전 κ΅¬μ—­μ—μ„œμ˜ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό ν˜„μž¬ ꡬ역에 적용
            dp[0][index] = min(dp[0][index], dp[state][index - 1] + int(state & 1 == 0) + int(state & 2 == 0))
        # ν˜„μž¬ ꡬ역과 인접 ꡬ역 λͺ¨λ‘λ₯Ό 컀버할 수 μžˆλŠ” 경우λ₯Ό 확인
        if enemy[0][index] + enemy[1][index] <= m:
            dp[0][index] = min(dp[0][index], dp[0][index - 1] + 1)
        # ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역(첫 번째 ν–‰)을 컀버할 수 μžˆλŠ” 경우λ₯Ό 확인
        if index < n - 1 and enemy[0][index] + enemy[0][index + 1] <= m:
            dp[1][index] = min(dp[0][index - 1] + 2, dp[2][index - 1] + 1)
        # ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역(두 번째 ν–‰)을 컀버할 수 μžˆλŠ” 경우λ₯Ό 확인
        if index < n - 1 and enemy[1][index] + enemy[1][index + 1] <= m:
            dp[2][index] = min(dp[0][index - 1] + 2, dp[1][index - 1] + 1)
        # 두 ν–‰μ˜ ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역을 λͺ¨λ‘ 컀버할 수 μžˆλŠ” 경우λ₯Ό 확인
        if index < n - 1 and enemy[0][index] + enemy[0][index + 1] <= m and enemy[1][index] + enemy[1][index + 1] <= m:
            dp[3][index] = dp[0][index - 1] + 2
    return dp

# ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€ μˆ˜ν–‰
for _ in range(int(input())):
    n, m = map(int, input().split())  # n: ꡬ역 수, m: μ΅œλŒ€ 컀버 κ°€λŠ₯ν•œ 적의 수
    enemy = [[*map(int, input().split()), 0] for _ in range(2)]  # 각 ν–‰μ˜ 적의 수
    result = solve(0)[0][n - 1]  # κΈ°λ³Έ μƒνƒœμ—μ„œ μ΅œμ†Œ μ†ŒλŒ€ 수 계산

    # 첫 λ²ˆμ§Έμ™€ λ§ˆμ§€λ§‰ ꡬ역이 ν•¨κ»˜ 컀버 κ°€λŠ₯ν•œ 경우의 μ΅œμ†Œ μ†ŒλŒ€ 수 계산
    if enemy[0][0] + enemy[0][n - 1] <= m:
        dp_temp = solve(1)
        result = min(result, dp_temp[2][n - 2] + 1, dp_temp[0][n - 2] + 2)
    if enemy[1][0] + enemy[1][n - 1] <= m:
        dp_temp = solve(2)
        result = min(result, dp_temp[1][n - 2] + 1, dp_temp[0][n - 2] + 2)
    if enemy[0][0] + enemy[0][n - 1] <= m and enemy[1][0] + enemy[1][n - 1] <= m:
        result = min(result, solve(3)[0][n - 2] + 2)

    print(result)  # κ³„μ‚°λœ μ΅œμ†Œ μ†ŒλŒ€ 수 좜λ ₯

μ½”λ“œμ˜ 핡심 ꡬ성

1. solve ν•¨μˆ˜:

  • μ—­ν• : 각 ꡬ역을 μ–΄λ–»κ²Œ 컀버할지에 따라 κ°€λŠ₯ν•œ λͺ¨λ“  μƒνƒœλ₯Ό κ³ λ €ν•˜μ—¬ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.
  • λ™μž‘ 방식:
    • dp 배열을 μ΄ˆκΈ°ν™”ν•˜μ—¬ 각 μƒνƒœλ³„λ‘œ 각 κ΅¬μ—­κΉŒμ§€ ν•„μš”ν•œ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό μ €μž₯ν•©λ‹ˆλ‹€. λ„€ κ°€μ§€ μƒνƒœλŠ” λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:
      1. ν˜„μž¬ ꡬ역을 μƒˆλ‘œμš΄ μ†ŒλŒ€λ‘œ μ»€λ²„ν•˜λŠ” 경우.
      2. ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역(첫 번째 ν–‰)을 ν•¨κ»˜ μ»€λ²„ν•˜λŠ” 경우.
      3. ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역(두 번째 ν–‰)을 ν•¨κ»˜ μ»€λ²„ν•˜λŠ” 경우.
      4. 두 ν–‰μ˜ ν˜„μž¬ ꡬ역과 λ‹€μŒ ꡬ역을 λͺ¨λ‘ μ»€λ²„ν•˜λŠ” 경우.
    • 각 μƒνƒœμ— 따라 이전 κ΅¬μ—­μ—μ„œμ˜ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό 기반으둜 ν˜„μž¬ κ΅¬μ—­μ˜ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.

2. 메인 둜직:

  • μ—­ν• : ν…ŒμŠ€νŠΈ μΌ€μ΄μŠ€μ— λŒ€ν•΄ μž…λ ₯을 λ°›κ³ , solve ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•˜μ—¬ κ²°κ³Όλ₯Ό κ³„μ‚°ν•˜κ³  좜λ ₯ν•©λ‹ˆλ‹€.
  • λ™μž‘ 방식:
    • 각 ν–‰μ˜ 적의 수λ₯Ό μž…λ ₯λ°›μŠ΅λ‹ˆλ‹€.
    • κΈ°λ³Έ μƒνƒœ(첫 번째 μƒνƒœ)μ—μ„œ μ‹œμž‘ν•˜μ—¬ μ΅œμ†Œ μ†ŒλŒ€ 수λ₯Ό κ³„μ‚°ν•©λ‹ˆλ‹€.
    • νŠΉλ³„ν•œ 경우(첫 λ²ˆμ§Έμ™€ λ§ˆμ§€λ§‰ ꡬ역이 ν•¨κ»˜ 컀버 κ°€λŠ₯ν•œ 경우)λ₯Ό μΆ”κ°€λ‘œ κ³ λ €ν•˜μ—¬ κ²°κ³Όλ₯Ό μ΅œμ ν™”ν•©λ‹ˆλ‹€.

μ½”λ“œμ˜ μ£Όμš” κ³ λ € 사항

  • 동적 ν”„λ‘œκ·Έλž˜λ°(Dynamic Programming): 이 λ¬Έμ œλŠ” 동적 ν”„λ‘œκ·Έλž˜λ°μ„ 톡해 효율적으둜 ν•΄κ²°λ©λ‹ˆλ‹€. 각 ꡬ역을 μ»€λ²„ν•˜λŠ” 데 ν•„μš”ν•œ μ΅œμ†Œ μ†ŒλŒ€ μˆ˜λŠ” 이전 κ΅¬μ—­μ˜ μƒνƒœμ— 따라 λ‹¬λΌμ§€λ―€λ‘œ, 이λ₯Ό κ³ λ €ν•˜μ—¬ 각 κ΅¬μ—­λ³„λ‘œ 졜적의 ν•΄λ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.
  • μƒνƒœ κ³ λ €: 각 ꡬ역을 μ»€λ²„ν•˜λŠ” λ‹€μ–‘ν•œ 방법(μƒνƒœ)을 κ³ λ €ν•΄μ•Ό ν•©λ‹ˆλ‹€. μ΄λŠ” 각 ꡬ역이 λ…λ¦½μ μœΌλ‘œ 컀버될 μˆ˜λ„ 있고, μΈμ ‘ν•œ ꡬ역과 ν•¨κ»˜ 컀버될 μˆ˜λ„ μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€.
  • 경계 쑰건 처리: 첫 λ²ˆμ§Έμ™€ λ§ˆμ§€λ§‰ ꡬ역이 νŠΉλ³„ν•œ 경우λ₯Ό ꡬ성할 수 μžˆμœΌλ―€λ‘œ, 이λ₯Ό λ³„λ„λ‘œ μ²˜λ¦¬ν•©λ‹ˆλ‹€.

image

 

λŒ“κΈ€