PS

[λ°±μ€€] 12100 2048(easy) with Python

ν˜•μ€€_It's 2021. 10. 25. 23:34
728x90
λ°˜μ‘ν˜•

πŸ“Œ BOJ 12100 2048(easy)

πŸ’‘ 쑰건

  1. λ³΄λ“œμ˜ ν¬κΈ°λŠ” N * N (1 ≀ N ≀ 20)
    0 은 빈칸, μ΄μ™Έμ˜ 값은 λΈ”λ‘μ˜ 값듀을 λ‚˜νƒ€λ‚Έλ‹€.
    블둝에 μ“°μ—¬ μžˆλŠ” μˆ˜λŠ” 2보닀 ν¬κ±°λ‚˜ κ°™κ³ , 1024보닀 μž‘κ±°λ‚˜ 같은 2의 μ œκ³±κΌ΄μ΄λ‹€.
    블둝은 적어도 ν•˜λ‚˜ μ£Όμ–΄μ§„λ‹€.

  2. 같은 값을 κ°–λŠ” 두 블둝이 μΆ©λŒν•˜λ©΄ 두 블둝은 ν•˜λ‚˜λ‘œ ν•©μ³μ§€κ²Œ λœλ‹€.

  3. ν•œ 번의 μ΄λ™μ—μ„œ 이미 합쳐진 블둝은 또 λ‹€λ₯Έ 블둝과 λ‹€μ‹œ ν•©μ³μ§ˆ 수 μ—†λ‹€.

  4. μ΅œλŒ€ λ‹€μ„―λ²ˆ 이동 μ‹œμΌœμ„œ 얻을 수 μžˆλŠ” κ°€μž₯ 큰 λΈ”λ‘μ˜ 값을 좜λ ₯.

  5. λ°±νŠΈλž˜ν‚Ή μ•Œκ³ λ¦¬μ¦˜ μœ ν˜•μ˜ 문제

πŸ–₯ μ†ŒμŠ€ μ½”λ“œ

from sys import stdin, setrecursionlimit
from collections import deque

setrecursionlimit(int(1e9))

n = int(stdin.readline())
arr = [list(map(int, stdin.readline().split())) for _ in range(n)]
answer, q = 0, deque()


def get(i, j):
    if arr[i][j]:  
        q.append(arr[i][j])  
        arr[i][j] = 0  


def merge(i, j, di, dj):  
    while q:
        x = q.popleft()  
        if not arr[i][j]:  
            arr[i][j] = x
        elif arr[i][j] == x:  
            arr[i][j] = x * 2  
            i, j = i + di, j + dj
        else:  
            i, j = i + di, j + dj
            arr[i][j] = x


def move(k):

    if k == 0:  
        for j in range(n):
            for i in range(n):
                get(i, j)
            merge(0, j, 1, 0)  
    elif k == 1:  
        for j in range(n):
            for i in range(n - 1, -1, -1):
                get(i, j)
            merge(n - 1, j, -1, 0)  
    elif k == 2:  
        for i in range(n):
            for j in range(n):
                get(i, j)
            merge(i, 0, 0, 1)  
    else:  
        for i in range(n):
            for j in range(n - 1, -1, -1):
                get(i, j)
            merge(i, n - 1, 0, -1)  


def recursive(count):
    global arr, answer
    if count == 5:  
        for i in range(n):
            answer = max(answer, max(arr[i]))  
        return
    b = [x[:] for x in arr]  

    for k in range(4):  
        move(k)  
        recursive(count + 1)  
        arr = [x[:] for x in b]


recursive(0)
print(answer)

πŸ”– 예제 및 μ‹€ν–‰κ²°κ³Ό

예제

3
2 2 2
4 4 4
8 8 8

μ‹€ν–‰κ²°κ³Ό

16

⌨️ 문제 풀이

  1. λ°±νŠΈλž˜ν‚Ήμ€ μž¬κ·€κ°€ κ°€μž₯ 핡심.
    λ°±νŠΈλž˜ν‚Ήμ„ μˆ˜ν–‰ν•˜λ©° μž¬κ·€λ₯Ό μ§„ν–‰ν•  recursiveν•¨μˆ˜μ— νŒŒλΌλ―Έν„°λ₯Ό cnt 둜 μ£Όκ³ , 첫 μ‹€ν–‰μ‹œμ—λŠ” 0을 μ£Όκ³  μ‹€ν–‰μ‹œν‚¨λ‹€.
  1. N의 크기가 μž‘κΈ° λ•Œλ¬Έμ— deep copyλ₯Ό μ΄μš©ν•œ 배열볡사가 κ°€λŠ₯ν•˜λ‹€.
    이λ₯Ό 톡해 λ°©ν–₯을 λ°”κΎΈκΈ° μ „, 이전 λ³΄λ“œμ˜ μƒνƒœλ₯Ό κΈ°μ–΅ν•˜κΈ° μœ„ν•œ μ†ŒμŠ€μ½”λ“œλ₯Ό μž‘μ„±ν•œλ‹€.
    움직이기 μ „ λ³΄λ“œμ˜ 상황을 기얡해두지 μ•ŠμœΌλ©΄, λ°±νŠΈλž˜ν‚Ήμ΄ μˆ˜ν–‰λ  수 μ—†λ‹€.
    b = [x[:] for x in arr]
  1. λ„€ λ°©ν–₯으둜 블둝을 움직일 수 μžˆμœΌλ‹ˆ, λ°˜λ³΅λ¬Έμ„ 톡해 λ„€ λ°©ν–₯으둜 움직여쀀닀.
    move() ν•¨μˆ˜μ—μ„œ k 의 값에 따라 λ„€ λ°©ν–₯으둜 움직여 μ€€λ‹€.
    def move(k):
     # arr[i][j]
     if k == 0:  # μœ„λ‘œ 이동, 블락듀이 μœ„λ‘œ λͺ¨λ‘ μ΄λ™ν•˜λ©΄ row indexλŠ” 0
         for j in range(n):
             for i in range(n):
                 get(i, j)
             merge(0, j, 1, 0)  # row index 1μ”© μ¦κ°€ν•˜λ©΄μ„œ μ•„λž˜μͺ½ 블락듀을 합쳐감
     elif k == 1:  # μ•„λž˜λ‘œ 이동, 블락듀이 μ•„λž˜λ‘œ λͺ¨λ‘ μ΄λ™ν•˜λ©΄ row indexλŠ” n-1
         for j in range(n):
             for i in range(n - 1, -1, -1):
                 get(i, j)
             merge(n - 1, j, -1, 0)  # row 인덱슀 1μ”© κ°μ†Œν•˜λ©΄μ„œ μœ„μͺ½λ“€μ„ 합쳐감
     elif k == 2:  # 였λ₯Έμͺ½μœΌλ‘œ 이동, column indexλŠ” 0
         for i in range(n):
             for j in range(n):
                 get(i, j)
             merge(i, 0, 0, 1)  # column 인덱슀 증가 였λ₯Έμͺ½μœΌλ‘œ 이동
     else:  # μ™Όμͺ½μœΌλ‘œ 이동, column indexλŠ” n-1
         for i in range(n):
             for j in range(n - 1, -1, -1):
                 get(i, j)
             merge(i, n - 1, 0, -1)  # column 인덱슀 κ°μ†Œ μ™Όμͺ½μœΌλ‘œ 이동
  1. get() ν•¨μˆ˜μ—μ„œ 움직일 λ³΄λ“œλ“€μ˜ μƒνƒœλ₯Ό ν™•μΈν•˜λ©΄μ„œ 순차적으둜 μˆœνšŒν•΄μ£Όκ³ ,
    μˆœνšŒν•˜λ©΄μ„œ λ°°μ—΄ μ›μ†Œμ˜ 값이 0이 μ•„λ‹Œ 경우, μ›μ†Œμ˜ 값을 큐에 λ„£μ–΄μ€€λ‹€.
    배열에 넣은 값이 있던 ν•΄λ‹Ή μžλ¦¬λŠ” 0으둜 λ°”κΏ”μ€€λ‹€.
    def get(i, j):
     if arr[i][j]:  # 0이 μ•„λ‹Œ 값이라면
         q.append(arr[i][j])  # queue에 arr의 값을 λ„£λŠ”λ‹€.
         arr[i][j] = 0  # μ²˜λ¦¬κ°€ 된 빈 μžλ¦¬λŠ” 0으둜 κ°’ μ—…λ°μ΄νŠΈ
  1. merge() ν•¨μˆ˜μ—μ„œ 각 μ΄λ™ν•˜λ €λŠ” λ°©ν–₯에 μ•Œλ§žκ²Œ 인덱슀λ₯Ό μ‘°μ ˆν•˜λ©° 큐가 λΉŒλ•ŒκΉŒμ§€ λ°˜λ³΅ν•˜λ©° 합쳐쀀닀.
    μ›€μ§μ΄λ €λŠ” κ°’μ˜ 블둝을 νμ—μ„œ κΊΌλ‚΄μ˜¨ ν›„, 놓을 곳의 λΈ”λŸ­μ˜ 값이 0이라면 κ·Έλƒ₯ 두고,
    값이 μΌμΉ˜ν•œλ‹€λ©΄ 2의 제곱 꼴이기에 2λ°°λ₯Ό ν•΄μ€€λ‹€.
    값이 일치 ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ κ·Έ μžλ¦¬μ— κ·ΈλŒ€λ‘œ λ‘”λ‹€.
def merge(i, j, di, dj):  # row index, column index, yλ°©ν–₯, xλ°©ν–₯
    while q:
        x = q.popleft()  # μ›€μ§μ΄λ €λŠ” 블둝 값을 κ°€μ Έμ˜¨λ‹€. FIFO
        if not arr[i][j]:  # 0이라면 κ·ΈλŒ€λ‘œ λ†“λŠ”λ‹€.
            arr[i][j] = x
        elif arr[i][j] == x:  # 값이 μΌμΉ˜ν•œλ‹€λ©΄
            arr[i][j] = x * 2  # ν•©μ³μ§€λ―€λ‘œ 2배둜 증가
            i, j = i + di, j + dj
        else:  # 값이 μΌμΉ˜ν•˜μ§€ μ•ŠμœΌλ©΄
            i, j = i + di, j + dj
            arr[i][j] = x
  1. move() ν•¨μˆ˜μ˜ μ²˜λ¦¬κ°€ 끝났닀면, cnt + 1 을 νŒŒλΌλ―Έν„°λ‘œ μ£Όκ³ , recursive ν•¨μˆ˜λ₯Ό μž¬κ·€ν˜ΈμΆœ ν•΄μ€€λ‹€.
  1. 3λ²ˆλΆ€ν„° λ‹€μ‹œ λ°˜λ³΅ν•˜λ©΄μ„œ, cnt 값이 5, 즉 λ‹€μ„―λ²ˆ μ›€μ§μ˜€μ„ λ•Œ, λ³΄λ“œνŒμ„ μˆœνšŒν•œλ‹€.
    각 λ°°μ—΄μ˜ μ΅œλŒ“κ°’κ³Ό μ •λ‹΅μœΌλ‘œ 좜λ ₯ν•  ans 값을 λΉ„κ΅ν•˜μ—¬ κ°±μ‹ ν•œλ‹€.

πŸ’Ύ λŠλ‚€μ 

  1. μž¬κ·€ν•¨μˆ˜λ₯Ό μ–Όλ§ˆλ‚˜ μ‘μš©μ„ ν•  수 μžˆλŠ”μ§€μ— λŒ€ν•œ λ¬Έμ œμ˜€λ‹€.
  2. get(), move() ν•¨μˆ˜λ₯Ό κ΅¬ν˜„ν•˜λŠ” 것이 κ°€μž₯ μ–΄λ €μ› μœΌλ©°, 이 뢀뢄은 λ‹€λ₯Έ λΈ”λ‘œκ·Έμ—μ„œ 아이디어λ₯Ό μ–»μ–΄ ν•΄κ²°ν–ˆλ‹€.
  3. λͺ‡ 번이고 λ‹€μ‹œ 풀어보기 쒋은 문제인 것 κ°™λ‹€. 주말에 λ‹€μ‹œ ν•œ 번 ν’€μ–΄λ³΄λŠ” 것이 μ’‹κ² λ‹€.
λ°˜μ‘ν˜•