티스토리 뷰

1. 문제
2048 게임은 4×4 크기의 보드에서 혼자 즐기는 재미있는 게임이다.
이 게임에서 한 번의 이동은 보드 위에 있는 전체 블록을 상하좌우 네 방향 중 하나로 이동시키는 것이다. 이때, 같은 값을 갖는 두 블록이 충돌하면 두 블록은 하나로 합쳐지게 된다. 한 번의 이동에서 이미 합쳐진 블록은 또 다른 블록과 다시 합쳐질 수 없다. (실제 게임에서는 이동을 한 번 할 때마다 블록이 추가되지만, 이 문제에서 블록이 추가되는 경우는 없다)
마지막으로, 똑같은 수가 세 개가 있는 경우에는 이동하려고 하는 쪽의 칸이 먼저 합쳐진다. 예를 들어, 위로 이동시키는 경우에는 위쪽에 있는 블록이 먼저 합쳐지게 된다. <그림 14>의 경우에 위로 이동하면 <그림 15>를 만든다.
이 문제에서 다루는 2048 게임은 보드의 크기가 N×N 이다. 보드의 크기와 보드판의 블록 상태가 주어졌을 때, 최대 5번 이동해서 만들 수 있는 가장 큰 블록의 값을 구하는 프로그램을 작성하시오.
2. 입력
첫째 줄에 보드의 크기 N (1 ≤ N ≤ 20)이 주어진다. 둘째 줄부터 N개의 줄에는 게임판의 초기 상태가 주어진다. 0은 빈 칸을 나타내며, 이외의 값은 모두 블록을 나타낸다. 블록에 쓰여 있는 수는 2보다 크거나 같고, 1024보다 작거나 같은 2의 제곱꼴이다. 블록은 적어도 하나 주어진다.
3. 출력
최대 5번 이동시켜서 얻을 수 있는 가장 큰 블록을 출력한다.
4. 해결방법
1. 브루트포스 + DFS (깊이 우선 탐색)
- 총 5번 이동 가능 → 각 이동마다 4가지 방향 가능 → 최대 탐색 경우의 수는 4^5 = 1024 (완전 탐색 가능)
- 따라서, 모든 경우의 수를 DFS로 탐색하여 최댓값을 추적
2. 각 방향으로 이동 구현
- 각 방향으로 블록들을 모으고(get) → 병합(merge)하는 방식으로 이동을 구현
- 병합 시 같은 숫자끼리는 한 번만 합쳐짐
3. 백트래킹
- 한 방향으로 이동한 후, 다음 DFS 탐색을 위해 원래 상태로 보드를 복원해야 함 → tmp_board 사용
5. 구현코드
from collections import deque
n = int(input())
board = [list(map(int, input().split())) for _ in range(n)]
max_block = 0 # 얻을 수 있는 가장 큰 블록 값
q = deque() # 블록 병합을 위한 큐
def get(i, j):
if board[i][j]:
q.append(board[i][j])
board[i][j] = 0
def merge(i, j, di, dj): #row idx, column idx, y방향, x방향
while q:
value = q.popleft()
if not board[i][j]: # 현재 칸이 비어있으면 그대로 채움
board[i][j] = value
elif board[i][j] == value: # 같은 값이면 병합
board[i][j] = value * 2
i, j = i + di, j + dj # 병합 후 다음 위치로 이동
else:
i, j = i + di, j + dj # 병합 불가 → 다음 칸에 넣음
board[i][j] = value
def move(d):
if d == 0: # 위
for j in range(n):
for i in range(n):
get(i, j)
merge(0, j, 1, 0)
elif d == 1: # 아래
for j in range(n):
for i in range(n - 1, -1, -1):
get(i, j)
merge(n - 1, j, -1, 0)
elif d == 2: # 왼쪽
for i in range(n):
for j in range(n):
get(i, j)
merge(i, 0, 0, 1)
elif d == 3: # 오른쪽
for i in range(n):
for j in range(n - 1, -1, -1):
get(i, j)
merge(i, n - 1, 0, -1)
def dfs(depth):
global max_block, board
if depth == 5: # 최대 5번 이동한 경우, 최대 블록 값 갱신
for i in range(n):
max_block = max(max_block, max(board[i]))
return
tmp_board = [x[:] for x in board] #방향 바꾸기 전 원래 보드 기억해야함
for d in range(4): # 4방향 모두 시도
move(d)
dfs(depth + 1)
board = [x[:] for x in tmp_board] # 이전 상태로 복원
dfs(0)
print(max_block)'알고리즘 > 백준 문제 풀이' 카테고리의 다른 글
| [백준/BOJ] 3190: 뱀 (Python 파이썬) (5) | 2025.08.05 |
|---|---|
| [백준/BOJ] 19237: 어른 상어 (Python 파이썬) (2) | 2025.08.04 |
| [백준/BOJ] 19236: 청소년 상어 (Python 파이썬) (4) | 2025.07.24 |
| [백준/BOJ] 20061: 모노미노도미노 2 (Python 파이썬) (1) | 2025.07.23 |
| [백준/BOJ] 17825: 주사위 윷놀이 (Python 파이썬) (3) | 2025.07.22 |
공지사항
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- 백준
- **
- 강의노트 정리
- 클래스 총 정리
- sorted
- ndarray
- 경사하강법
- **kwargs
- Andrew Ng
- 강화학습
- 파이썬
- *args
- 머신러닝
- 숏코딩
- ML
- 로지스틱 회귀
- 앤드류응
- Sort
- Action spaces
- cnn
- ML 프로세스
- python
- ML 종류
- NumPy
- ML Process
- 손실함수
- 비용함수
- *
- 딥러닝
- baekjoon
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 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 |
글 보관함
