λ³Έλ¬Έ λ°”λ‘œκ°€κΈ°

μ•Œκ³ λ¦¬μ¦˜ 문제

λ°±μ€€ 12094 - 2048 (Hard) [파이썬]

풀이

이전에 ν’€μ—ˆλ˜ 2048 (Easy) 문제의 풀이 λ°©λ²•μ—μ„œλŠ” λͺ¨λ“  경우의 수λ₯Ό νƒμƒ‰ν•˜μ—¬ 닡을 λ„μΆœν–ˆλ‹€λ©΄ 2048 (Hard)λŠ” 10회의 μ΄λ™μœΌλ‘œ ν™•μž₯λ˜μ—ˆκΈ° λ•Œλ¬Έμ— 적절히 κ°€μ§€μΉ˜κΈ°λ₯Ό ν•˜μ—¬ μ‹œκ°„μ„ 쀄여 닡을 λ„μΆœν•΄μ•Ό ν•©λ‹ˆλ‹€. 그럼, μ–΄λ–€ 경우λ₯Ό κ°€μ§€μΉ˜κΈ°ν•΄μ£Όμ–΄μ•Ό ν• κΉŒμš”?

 

 

  • 블둝듀을 μ΄λ™μ‹œμΌ°λŠ”λ° 이전과 같은 λͺ¨μŠ΅μΌ 경우

λ‹¨μˆœν•˜κ²Œ 생각해봀을 λ•Œ κ°€μž₯ λ¨Όμ € λ– μ˜€λ₯΄λŠ” λ°©λ²•μž…λ‹ˆλ‹€.

 

μ–΄λ–€ ν•œ κ²½μš°μ— λŒ€ν•˜μ—¬ μƒν•˜μ’Œμš°λ₯Ό λͺ¨λ‘ κ΅¬ν•˜κΈ° λ•Œλ¬Έμ— μƒν•˜μ’Œμš° 쀑 같은 λͺ¨μ–‘을 κ°€μ§„ κ²½μš°κ°€ λ°œμƒν•˜λ©΄ μ• μ΄ˆμ— 탐색할 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€. μ€‘λ³΅λœ 경우λ₯Ό νƒμƒ‰ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

 

 

  • κ΅¬ν•œ μ΅œλŒ“κ°’μ΄ 이전에 κ΅¬ν•œ 것보닀 μž‘μ„ κ²ƒμ΄λΌλŠ” 게 μ˜ˆμƒλ˜λŠ” 경우

이 κ²½μš°λŠ” 저도 λ°±μ€€ 질문 κ²€μƒ‰μ—μ„œ μ–»μ–΄λ‚Έ ν•΄λ‹΅μž…λ‹ˆλ‹€.

 

예λ₯Ό λ“€μ–΄ μ²˜μŒμ— μ΅œλŒ€ 10회 이동에 λŒ€ν•΄ νƒμƒ‰ν•˜μ˜€λ”λ‹ˆ 512λΌλŠ” μˆ˜κ°€ μ΅œλŒ“κ°’μ΄ λ˜μ—ˆλ‹€κ³  ν•©μ‹œλ‹€. 그럼 2048 κ²Œμž„ νŠΉμ„±μ— μ˜ν•΄ 9회 μ΄λ™μ—λŠ” 적어도 μ΅œλŒ“κ°’μ΄ 256이 λ˜μ—ˆμ„ 것이고, 8회 μ΄λ™μ—λŠ” 128, 7회 μ΄λ™μ—λŠ” 64와 같이 이동 νšŸμˆ˜κ°€ 1회 κ°μ†Œν•  λ•Œλ§ˆλ‹€ μ΅œλŒ“κ°’μ΄ 적어도 μ ˆλ°˜μ”© μž‘μ•„μ‘ŒμŒμ„ μ˜ˆμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€.

 

그러면, μ–΄λ–€ 경우의 10회 μ΅œλŒ“κ°’μ„ κ΅¬ν•˜λ©΄ 1νšŒκΉŒμ§€μ˜ μ˜ˆμΈ‘λ˜λŠ” μ΅œλŒ“κ°’μ„ 기둝할 수 있게 되고 μ–΄λ–€ n회 μ΄λ™μ˜ κ²½μš°μ—μ„œμ˜ μ΅œλŒ“κ°’μ΄ μ•„κΉŒ κ΅¬ν•œ 1~10νšŒκΉŒμ§€μ˜ μ˜ˆμΈ‘λ˜λŠ” μ΅œλŒ“κ°’μ˜ n회 μ΅œλŒ“κ°’ 보닀 μž‘λ‹€λ©΄ 버릴 수 있게 λ©λ‹ˆλ‹€.

 

μ½”λ“œλ‘œ 보이면 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€.

max_num = 0
# ν˜„μž¬ n회 μ΄λ™μ—μ„œμ˜ μ΅œλŒ“κ°’μ„ κ΅¬ν•˜μ—¬
for i in range(N):
    max_num = max(max_num, max(board[i]))
# 이전에 κ΅¬ν–ˆλ˜ n회 μ΄λ™μ˜ μ΅œλŒ“κ°’λ³΄λ‹€ μž‘λ‹€λ©΄ ν˜„μž¬ 경우의 μˆ˜λŠ” μ–΄λ–»κ²Œ μ΄λ™ν•˜λ˜κ°„μ—
# 이전에 κ΅¬ν•œ μ΅œλŒ“κ°’λ³΄λ‹€ μž‘λ‹€.
if (max_num <= max_list[deep]): return

μ›λž˜λŒ€λ‘œλΌλ©΄ 이 두 경우만 잘 κ΅¬ν˜„ν•˜λ©΄ μ„±κ³΅μž…λ‹ˆλ‹€.

 

근데 μ € 같은 κ²½μš°λŠ” 이전에 ν’€μ—ˆλ˜ '2048 (Easy)'μ—μ„œ λ³΄λ“œλ₯Ό μ›€μ§μ΄λŠ” μ•Œκ³ λ¦¬μ¦˜μ„ 삼쀑 for문으둜 κ΅¬ν˜„ν•˜μ—¬μ„œ 자꾸 10%μ—μ„œ μ‹œκ°„ μ΄ˆκ³Όκ°€ λ‚¬μ—ˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μ²˜μŒμ—” κ°€μ§€μΉ˜κΈ°κ°€ 문제인 쀄 μ•Œμ•˜λŠ”λ° 삼쀑 for문이 λ¬Έμ œμ˜€κ³  이쀑 for문으둜 ν•΄κ²°ν•˜μ˜€μŠ΅λ‹ˆλ‹€.

 

μ €μ²˜λŸΌ 삼쀑이 μ•„λ‹ˆλΌ 이쀑 for문으둜 λ§Œλ“œμ…¨λ‹€λ©΄ μ• μ΄ˆμ— λ¬Έμ œμ—†μ΄ 될 것 κ°™μŠ΅λ‹ˆλ‹€!!

 

μ½”λ“œ

import sys
input = sys.stdin.readline

N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
mNum = 0
for i in range(N):
    mNum = max(mNum, max(board[i]))
max_num = 0
max_list = [0 for _ in range(11)]

def board_move(wasd):
    if (wasd == 0): # μœ„
        for column in range(N):
            top = 0
            for row in range(1, N):
                if board[row][column] != 0:
                    temp = board[row][column]
                    board[row][column] = 0
                
                    if board[top][column] == 0:
                        board[top][column] = temp
                    elif board[top][column] == temp:
                        board[top][column] <<= 1
                        top += 1
                    else:
                        top += 1
                        board[top][column] = temp
    elif (wasd == 1): # μ•„λž˜
        for column in range(N):
            top = N-1
            for row in range(N-2, -1, -1):
                if board[row][column] != 0:
                    temp = board[row][column]
                    board[row][column] = 0
                
                    if board[top][column] == 0:
                        board[top][column] = temp
                    elif board[top][column] == temp:
                        board[top][column] <<= 1
                        top -= 1
                    else:
                        top -= 1
                        board[top][column] = temp
    elif (wasd == 2): # μ™Όμͺ½
        for row in range(N):
            top = 0
            for column in range(1, N):
                if board[row][column] != 0:
                    temp = board[row][column]
                    board[row][column] = 0
                
                    if board[row][top] == 0:
                        board[row][top] = temp
                    elif board[row][top] == temp:
                        board[row][top] <<= 1
                        top += 1
                    else:
                        top += 1
                        board[row][top] = temp
    elif (wasd == 3):
        for row in range(N):
            top = N-1
            for column in range(N-2, -1, -1):
                if board[row][column] != 0:
                    temp = board[row][column]
                    board[row][column] = 0
                
                    if board[row][top] == 0:
                        board[row][top] = temp
                    elif board[row][top] == temp:
                        board[row][top] <<= 1
                        top -= 1
                    else:
                        top -= 1
                        board[row][top] = temp

def n_2048(deep):
    global mNum, board, max_num

    max_num = 0
    for i in range(N):
        max_num = max(max_num, max(board[i]))
    if (max_num <= max_list[deep]): return

    if (deep == 10):
        mNum = max(mNum, max_num)
        max_num = mNum
        if (max_list[10] < max_num):
            for i in range(10, 0, -1):
                max_list[i] = max_num
                max_num //= 2
        return
    
    bd = [b[:] for b in board]
    for i in range(4):
        board_move(i)
        if (bd == board):
            continue
        n_2048(deep + 1)
        board = [b[:] for b in bd]

n_2048(0)
print(mNum)