목차
- 미로 탈출 넘버원 (1)
- 지도와 폭탄 (1)
- 테트리스
- 알까기 챔피언 (1)
- 최소 합차 (1)
1. 미로 탈출 넘버원 (1)



풀이
import collections
def solution(N, M, maze):
rows = N
cols = M
def bfs():
directions = [(-1, 0), (1, 0), (0, -1), (0, 1)]
visited = [[False]*M for _ in range(N)]
que = collections.deque()
que.append((0, 0, 0)) # x, y, 거리
visited[0][0] = True
while que:
x, y, dist = que.popleft()
if (x, y) == (N-1, M-1):
return dist
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < rows and 0 <= ny < cols:
if not visited[nx][ny] and maze[nx][ny] == 0:
visited[nx][ny] = True
que.append((nx, ny, dist+1))
return -1
return bfs()
Testcase
# 테스트 1
입력값 〉 6, 6, [[0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 0], [0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 1], [0, 0, 0, 0, 1, 0], [1, 1, 1, 0, 0, 0]]
기댓값 〉 16
2. 지도와 폭탄 (1)



풀이
내 코드
import collections
def solution(N, M, maze):
rows = N
cols = M
directions = [(1, 0), (-1, 0), (0, 1), (0, -1)]
def bfs(dmaze):
visited = [[False]*N for _ in range(M)]
que = collections.deque()
que.append((0, 0, 0))
visited[0][0] = True
while que:
x, y, dist = que.popleft()
if (x, y) == (N-1, M-1):
return dist
for dx, dy in directions:
nx, ny = x + dx, y + dy
if 0 <= nx < rows and 0 <= ny < cols:
if not visited[nx][ny] and maze[nx][ny] == 0:
visited[nx][ny] = True
que.append((nx, ny, dist + 1))
return -1
# 1인 곳 찾기
blocks = []
for i in range(N):
for j in range(M):
if maze[i][j] == 1:
blocks.append((i, j))
results = []
for a, b in blocks:
maze[a][b] = 0
retv = bfs(maze)
if retv != -1:
results.append(retv)
maze[a][b] = 1
results.sort()
return -1 if len(results) == 0 else results[0]
정답코드
def solution(N, M, maze):
q = []
q.append((0, 0, 1))
di = [0, 0, 1, -1]
dj = [1, -1, 0, 0]
visited = [[[0 for _ in range(2)] for _ in range(M)] for _ in range(N)]
while q:
i, j, k = q.pop(0)
if (i, j) == (N-1, M-1):
return visited[i][j][k]
for di_, dj_ in zip(di, dj):
new_i = i + di_
new_j = j + dj_
if new_i < 0 or new_i >= N or new_j < 0 or new_j >= M:
continue
if visited[new_i][new_j][k] > 0:
continue
if maze[new_i][new_j] == 1 and k == 1:
q.append((new_i, new_j, k-1))
visited[new_i][new_j][k-1] = visited[i][j][k] + 1
if maze[new_i][new_j] == 0:
q.append((new_i, new_j, k))
visited[new_i][new_j][k] = visited[i][j][k] + 1
return -1
Testcase
# 테스트 1
입력값 〉 6, 6, [[0, 0, 0, 0, 0, 0], [0, 1, 1, 1, 1, 0], [0, 1, 0, 0, 0, 0], [1, 1, 0, 1, 0, 1], [0, 0, 0, 0, 1, 0], [1, 1, 1, 0, 0, 0]]
기댓값 〉 10
3. 테트리스





풀이
"""
* 시뮬레이션 문제로, 모두가 익숙한 테트리스 문제입니다.
* 차근 차근 구현하면 어렵지 않지만, 빠르고 정확하게 구현하는 것이 관건입니다.
* 익숙한 대상으로 시뮬레이션 연습을 하고, 추후에는 새로운 시뮬레이션 대상이
* 문제로 주어졌을 때 해결하는 연습을 하도록 합시다.
"""
# 테트리스의 블록별 기본형과 변형 형태는 코드로 주어집니다.
TETRIS_BLOCK = []
BLOCK = []
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 0, 0, 0],
[0, 1, 1, 1],
[0, 0, 0, 1]],
[[0, 0, 1],
[0, 0, 1],
[0, 1, 1]],
[[0, 0, 0, 0],
[0, 1, 0, 0],
[0, 1, 1, 1]],
[[0, 1, 1],
[0, 1, 0],
[0, 1, 0]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 0, 0, 0],
[0, 1, 1, 1],
[0, 1, 0, 0]],
[[0, 1, 1],
[0, 0, 1],
[0, 0, 1]],
[[0, 0, 0, 0],
[0, 0, 0, 1],
[0, 1, 1, 1]],
[[0, 1, 0],
[0, 1, 0],
[0, 1, 1]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 0, 1, 0],
[0, 1, 1, 1]],
[[0, 0, 1, 0],
[0, 0, 1, 1],
[0, 0, 1, 0]],
[[0, 0, 0, 0],
[0, 1, 1, 1],
[0, 0, 1, 0]],
[[0, 0, 1],
[0, 1, 1],
[0, 0, 1]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 0, 1],
[0, 1, 1],
[0, 1, 0]],
[[0, 0, 0],
[1, 1, 0],
[0, 1, 1]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 1, 0],
[0, 1, 1],
[0, 0, 1]],
[[0, 0, 0],
[0, 1, 1],
[1, 1, 0]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 0, 1],
[0, 0, 1],
[0, 0, 1],
[0, 0, 1]],
[[0, 0, 0, 0],
[1, 1, 1, 1]]]
TETRIS_BLOCK.append(BLOCK)
BLOCK = [[[0, 1, 1],
[0, 1, 1]]]
TETRIS_BLOCK.append(BLOCK)
def solution(blocks, commands):
WIDTH = 10
HEIGHT = 15
board = [[0 for _ in range(WIDTH)] for _ in range(HEIGHT)]
if len(blocks) == 0:
return 0
block_ind = 0
pos = 0
score = 0
shape = 0
ind = 0
while True:
if ind >= len(commands) or block_ind >= len(blocks):
break
curr_blocks = TETRIS_BLOCK[blocks[block_ind]]
curr_block = curr_blocks[shape]
if commands[ind] == 'u':
shape = (shape + 1) % len(curr_blocks)
elif commands[ind] == 'l':
is_possible = True
for i in range(len(curr_block)):
for j in range(len(curr_block[0])):
if j + pos - 1 < 0 and curr_block[i][j] == 1:
is_possible = False
break
if not is_possible:
break
if is_possible:
pos -= 1
elif commands[ind] == 'r':
is_possible = True
for i in range(len(curr_block)):
for j in range(len(curr_block[0])):
if j + pos + 1 >= WIDTH and curr_block[i][j] == 1:
is_possible = False
break
if not is_possible:
break
if is_possible:
pos += 1
elif commands[ind] == 'd':
for i in range(len(curr_block)):
for j in range(len(curr_block[0])):
if curr_block[i][j] == 1 and board[i][j + pos] == 1:
return score
pos_y = 0
is_done = False
while True:
for i in range(len(curr_block)):
for j in range(len(curr_block[0])):
if curr_block[i][j] == 1 and i + pos_y + 1 >= HEIGHT:
is_done = True
elif curr_block[i][j] == 1 and board[i+pos_y+1][j+pos] == 1:
is_done = True
if is_done:
break
if is_done:
break
if is_done:
break
pos_y += 1
for i in range(len(curr_block)):
for j in range(len(curr_block[0])):
if curr_block[i][j] == 1:
board[i+pos_y][j+pos] = 1
lines_lut = []
for i in range(HEIGHT):
if sum(board[i]) == WIDTH:
score += 1
lines_lut = [-1] + lines_lut
else:
lines_lut.append(i)
for i, di in enumerate(lines_lut):
for j in range(WIDTH):
if di < 0:
board[i][j] = 0
else:
board[i][j] = board[di][j]
pos = 0
shape = 0
block_ind += 1
ind += 1
return score
# blocks = [1, 3, 6, 2, 4, 7, 4, 5, 3]
# commands = "uulduuuldurrrrrdrrurrrrrduulldrrrldrdrlrrruudurrrrd"
# print(solution(blocks, commands))
Testcase
# 테스트 1
입력값 〉 [1, 3, 6, 2, 4, 7, 4, 5, 3], "uulduuuldurrrrrdrrurrrrrduulldrrrldrdrlrrruudurrrrd"
기댓값 〉 2
4. 알까기 챔피언 (1)



풀이
"""
* 이 문제는 DFS로 탐색하는 문제입니다.
* 탐색 아이디어 자체는 간단하지만, 조건에 맞게 구현하는 난이도가 상당한 문제입니다.
* 각 돌을 상하좌우로 치는 경우를 모두 따져보되, 다른 돌과 부딛히면 연쇄적으로 처리하는 것이 핵심입니다.
* board를 매번 만들어서 dfs하도록 구현하였지만, board를 사용하지 않을 경우 더 효율적인 구현이 됩니다.
* 단, 난이도가 높아져서 구현하는 시간이 더 오래 걸리니, 메모리가 부족한 경우 구현을 고려해볼 수 있습니다.
*/
"""
from copy import deepcopy
def solution(enemies, players):
result = float('inf')
def dfs(count, enemies, players):
nonlocal result
board = make_board(enemies, players)
H = len(board)
W = len(board[0])
if len(enemies) == 0:
if result > count:
result = count
return
if len(players) == 0:
return
if count >= result:
return
for x, y in players:
# direction 1
new_board = deepcopy(board)
curr = new_board[y][x]
moved_y = y
while curr:
new_board[moved_y][x] = 0
while moved_y - 1 >= 0 and new_board[moved_y - 1][x] == 0:
moved_y -= 1
if moved_y == 0:
break
else:
new_board[moved_y][x] = curr
curr = new_board[moved_y - 1][x]
moved_y -= 1
e, p = rocks_from_board(new_board)
dfs(count + 1, e, p)
# direction 2
new_board = deepcopy(board)
curr = new_board[y][x]
moved_y = y
while curr:
new_board[moved_y][x] = 0
while moved_y + 1 < H and new_board[moved_y + 1][x] == 0:
moved_y += 1
if moved_y == H - 1:
break
else:
new_board[moved_y][x] = curr
curr = new_board[moved_y + 1][x]
moved_y += 1
e, p = rocks_from_board(new_board)
dfs(count + 1, e, p)
# direction 3
new_board = deepcopy(board)
curr = new_board[y][x]
moved_x = x
while curr:
new_board[y][moved_x] = 0
while moved_x - 1 >= 0 and new_board[y][moved_x - 1] == 0:
moved_x -= 1
if moved_x == 0:
break
else:
new_board[y][moved_x] = curr
curr = new_board[y][moved_x - 1]
moved_x -= 1
e, p = rocks_from_board(new_board)
dfs(count + 1, e, p)
# direction 4
new_board = deepcopy(board)
curr = new_board[y][x]
moved_x = x
while curr:
new_board[y][moved_x] = 0
while moved_x + 1 < W and new_board[y][moved_x + 1] == 0:
moved_x += 1
if moved_x == W - 1:
break
else:
new_board[y][moved_x] = curr
curr = new_board[y][moved_x + 1]
moved_x += 1
e, p = rocks_from_board(new_board)
dfs(count + 1, e, p)
dfs(0, enemies, players)
return result
def make_board(enemies, players):
x_min = min((x[0] for x in enemies + players))
x_max = max((x[0] for x in enemies + players))
y_min = min((x[1] for x in enemies + players))
y_max = max((x[1] for x in enemies + players))
for i in range(len(enemies)):
enemies[i] = [enemies[i][0] - x_min, enemies[i][1] - y_min]
for i in range(len(players)):
players[i] = [players[i][0] - x_min, players[i][1] - y_min]
W = x_max - x_min + 1
H = y_max - y_min + 1
board = [[0 for _ in range(W)] for _ in range(H)]
for x, y in enemies:
board[y][x] = 1
for x, y in players:
board[y][x] = 2
return board
def rocks_from_board(board):
enemies = []
players = []
for i in range(len(board)):
for j in range(len(board[0])):
if board[i][j] == 1:
enemies.append([j, i])
elif board[i][j] == 2:
players.append([j, i])
return enemies, players
Testcase
# 테스트 1
입력값 〉 [[0, 12], [9, 14], [9, 9], [4, 0]], [[4, 5], [9, 4]]
기댓값 〉 4
5. 최소 합차 (1)


풀이
"""
* 이 문제는 누적합을 이용하여 연산을 최소화 하는 문제입니다.
* 수학적인 센스가 필요한 문제라고 할 수 있겠습니다!
"""
def solution(nums):
n = len(nums) // 3
cumsum = [0 for _ in range(len(nums))]
cumsum[0] = nums[0]
for i in range(1, len(nums)):
cumsum[i] = cumsum[i-1] + nums[i]
min_diff = float('inf')
sum_second = cumsum[3*n-1] - cumsum[2*n-1]
for i in range(n):
if i == 0:
sum_first = cumsum[2*n-1] - cumsum[n-1]
else:
sum_first = cumsum[i-1] + cumsum[2*n-1] - cumsum[n-1+i]
diff = sum_first - sum_second
min_diff = min(min_diff, diff)
sum_first = cumsum[n-1]
for i in range(n+1):
sum_second = cumsum[2*n-1-i] - cumsum[n-1] + cumsum[3*n-1] - cumsum[3*n-1-i]
diff = sum_first - sum_second
min_diff = min(min_diff, diff)
return min_diff
Testcase
# 테스트 1
입력값 〉 [7, 9, 5, 8, 1, 3]
기댓값 〉 3
# 테스트 2
입력값 〉 [5, 2, 3, 5, 9, 14, 2, 3, 15, 19, 4, 6]
기댓값 〉 -32
출처
해당 문제와 코드는 제로베이스(ZeroBase)에서 제공받았습니다.
모든 자료는 저작권법에 의하여 보호받는 저작물로서 이에 대한 무단 복제 및 배포를 원칙적으로 금합니다.
Comment