블록 이동하기 [프로그래머스 60063]
https://school.programmers.co.kr/learn/courses/30/lessons/60063
로봇의 길이가 2인 점과 회전할 수 있다는 점에서 다소 어려움을 느꼈다. 길이가 한 점일 때는 어떻게 풀었을까 생각을 해봤고 길이가 2이면 이터러블 객체에 2개의 좌표를 넣으면 된다고 생각했다. 다소 코드가 복잡해지고 변수가 많아지지만 꼼꼼히 작성하여 해결할 수 있었다
from collections import deque
def get_next_pos(pos, board):
next_pos = [] # 가능한 다음 위치
pos = list(pos) # 현재 위치
pos1_x, pos1_y, pos2_x, pos2_y = pos[0][0], pos[0][1], pos[1][0], pos[1][1] # 2개 위치 x, y 좌표
dx = [0, 0, 1, -1] #상하좌우
dy = [1, -1, 0, 0]
for i in range(4):
#상하좌우로 가능한 좌표들
pos1_next_x, pos1_next_y, pos2_next_x, pos2_next_y = pos1_x + dx[i], pos1_y + dy[i], pos2_x + dx[i], pos2_y + dy[i]
#가능한 좌표들이 비어있으면 리스트에 추가
if board[pos1_next_x][pos1_next_y] == 0 and board[pos2_next_x][pos2_next_y] == 0:
next_pos.append({(pos1_next_x, pos1_next_y), (pos2_next_x, pos2_next_y)})
if pos1_x == pos2_x: #가로로 있을 때
for i in [-1, 1]: #위로 회전 아래로 회전할 때
if board[pos1_x + i][pos1_y] == 0 and board[pos2_x + i][pos2_y] == 0:
next_pos.append({(pos1_x, pos1_y), (pos1_x + i, pos1_y)})
next_pos.append({(pos2_x, pos2_y), (pos2_x + i, pos2_y)})
elif pos1_y == pos2_y: #세로로 있을 때
for i in [-1, 1]: #위로 회전 아래로 회전할 때
if board[pos1_x][pos1_y + i] == 0 and board[pos2_x][pos2_y + i] == 0:
next_pos.append({(pos1_x, pos1_y), (pos1_x, pos1_y + i)})
next_pos.append({(pos2_x, pos2_y), (pos2_x, pos2_y + i)})
return next_pos
def solution(board):
answer = 0
n = len(board)
new_board = [[1] * (n + 2) for _ in range(n + 2)] # 벽을 바깥에 만들어줌
for i in range(n):
for j in range(n):
new_board[i + 1][j + 1] = board[i][j]
q = deque()
visited = [] # 방문한 pos 등록
pos = {(1, 1), (1, 2)}
q.append((pos, 0))
visited.append(pos)
while q:
pos, cost = q.popleft()
if (n, n) in pos: # 끝점에 도달하면
return cost # 시간 반환
for next_pos in get_next_pos(pos, new_board): #이동 가능한 점들
if next_pos not in visited: #들린 적 없으면
q.append((next_pos, cost + 1))
visited.append(next_pos)
return 0