728x90
문제 이해하기
2048 게임은 4×4 크기의 보드에서 숫자 블록을 이동시키며 즐기는 게임이다. 하지만 이번 문제에서는 보드의 크기가 N×N (1 ≤ N ≤ 20)으로 주어지고, 최대 5번의 이동으로 만들 수 있는 가장 큰 블록의 값을 찾아야 한다.
게임 규칙 정리
- 상하좌우 네 방향으로 보드의 모든 블록을 한꺼번에 이동시킬 수 있다.
- 같은 숫자를 가진 두 블록이 충돌하면 하나로 합쳐진다.
- 한 번의 이동에서 이미 합쳐진 블록은 다시 합쳐질 수 없다.
- 최대 5번 이동하여 가장 큰 블록의 값을 구해야 한다.
해결 방법: DFS로 모든 경우의 수 탐색하기
이 문제는 모든 가능한 이동 조합을 시도해보는 방법으로 해결할 수 있다. 최대 이동 횟수가 5번이므로, 가능한 이동의 수는 4^5 = 1024가지이다. 따라서 DFS(깊이 우선 탐색)을 사용하여 모든 경우를 탐색해도 충분하다.
DFS란?
DFS는 한 방향으로 갈 수 있을 때까지 깊게 들어가고, 더 이상 갈 곳이 없으면 이전 노드로 돌아오는 방식이다. 이 문제에서는 이동 횟수를 깊이로 생각하고, 각 이동마다 네 방향으로 분기하여 최대 깊이 5까지 탐색한다.
구현 단계
- 입력 받기
- 보드의 크기 N과 초기 상태를 입력받는다.
- 블록 이동 함수 구현
- 보드를 특정 방향으로 이동시키는 함수를 만든다.
- 이동 시 블록의 합쳐짐과 이미 합쳐진 블록은 다시 합쳐지지 않음을 처리해야 한다.
- DFS 함수 구현
- 현재 보드 상태와 이동 횟수를 인자로 받는다.
- 이동 횟수가 5보다 크면 종료한다.
- 네 방향으로 이동시킨 새로운 보드 상태로 DFS를 재귀 호출한다.
- 각 단계에서 가장 큰 블록의 값을 갱신한다.
- 최대 값 갱신
- 모든 DFS 탐색이 끝나면 최대 값을 출력한다.
최종 코드는 아래와 같다.
import sys
import copy
sys.setrecursionlimit(100000)
N = int(input())
board = [list(map(int, input().split())) for _ in range(N)]
max_block = 0
def move(board, direction):
N = len(board)
new_board = [[0]*N for _ in range(N)]
merged = [[False]*N for _ in range(N)]
if direction == 0: # 위로 이동
for j in range(N):
index = 0
for i in range(N):
if board[i][j]:
temp = board[i][j]
board[i][j] = 0
if new_board[index][j] == 0:
new_board[index][j] = temp
elif new_board[index][j] == temp and not merged[index][j]:
new_board[index][j] *= 2
merged[index][j] = True
index += 1
else:
index += 1
new_board[index][j] = temp
elif direction == 1: # 아래로 이동
for j in range(N):
index = N - 1
for i in range(N-1, -1, -1):
if board[i][j]:
temp = board[i][j]
board[i][j] = 0
if new_board[index][j] == 0:
new_board[index][j] = temp
elif new_board[index][j] == temp and not merged[index][j]:
new_board[index][j] *= 2
merged[index][j] = True
index -= 1
else:
index -= 1
new_board[index][j] = temp
elif direction == 2: # 왼쪽으로 이동
for i in range(N):
index = 0
for j in range(N):
if board[i][j]:
temp = board[i][j]
board[i][j] = 0
if new_board[i][index] == 0:
new_board[i][index] = temp
elif new_board[i][index] == temp and not merged[i][index]:
new_board[i][index] *= 2
merged[i][index] = True
index += 1
else:
index += 1
new_board[i][index] = temp
else: # 오른쪽으로 이동
for i in range(N):
index = N - 1
for j in range(N-1, -1, -1):
if board[i][j]:
temp = board[i][j]
board[i][j] = 0
if new_board[i][index] == 0:
new_board[i][index] = temp
elif new_board[i][index] == temp and not merged[i][index]:
new_board[i][index] *= 2
merged[i][index] = True
index -= 1
else:
index -= 1
new_board[i][index] = temp
return new_board
def dfs(board, depth):
global max_block
if depth == 5:
for i in range(N):
max_block = max(max_block, max(board[i]))
return
for i in range(4):
new_board = move(copy.deepcopy(board), i)
dfs(new_board, depth + 1)
dfs(board, 0)
print(max_block)
도움이 되셨다면 공감 및 댓글 부탁드립니다.
728x90
'Python > 백준' 카테고리의 다른 글
백준 테트로미노 [14500] Python 코드 + 해설 (0) | 2024.10.22 |
---|---|
백준 주사위 굴리기 [14499] Python 코드 + 해설 (0) | 2024.10.22 |
백준 시험 감독 [13458] Python 코드 + 해설 (1) | 2024.10.22 |
백준 뱀 [3190] Python 코드 + 해설 (0) | 2024.10.22 |
백준 구슬 탈출 2 [13460] Python 코드 + 해설 (1) | 2024.10.21 |