[골드 4] https://www.acmicpc.net/problem/3190
문제 유형 : 구현(시뮬레이션), 덱
해설 없이 스스로 풀었나요?
O
예제 출력 방향 전환을 이상하게 해서 문제 이해하는 데 시간이 너무 오래 걸렸다.
뱀의 이동을 큐로 구현해야 된다는 깨달음을 조금 더 일찍 얻었다면 ..
행 열 ny nx를 한 부분에서 반대로 써서 틀리고 있었따..
이 문제의 포인트는 뱀이 이동하는 좌표를 큐에 넣는 것이다.
뱀이 이동하며 꼬리는 자르고(popleft), 머리는 이동한 새로운 좌표를 추가(append)한다.
(필자는 큐를 생각 못하고.. 구현하다가, 뱀이 회전 하는데 꼬리의 좌표를 어떻게 자르지.. 하고 고민 중 큐라는 자료구조가 번뜩였다.)
풀이과정
먼저, 1, 2, 3은 그대로 구현할 수 있다.
4-1 위에서 언급한 대로 큐 자료형을 이용한다.
처음 시작할 때의 위치 (0,0)을 큐에 넣어 몸길이 1인 뱀의 초기 상태를 저장한다.
이후 오른쪽으로 한 칸 이동하면 (0,0)을 큐에서 pop하고, (0,1)을 큐에 push하여 뱀의 위치 상태를 변경한다.
즉, 큐가 뱀의 몸을 나타낸다고 생각하면 된다.
4-2 그래프에 사과가 있는 경우, 즉 board[y][x] == 2인 경우에는 뱀의 머리만 전진하므로 큐에서 pop하지 않고, 전진하여 머리가 있는 위치를 큐에 push하여 뱀의 몸 길이를 늘려준다.
5 방향 전환
나는 노가다로 케이스를 나누어서 구현했는데 오른쪽으로 방향 전환, 왼쪽으로 방향 전환이 '회전' 을 나타내는 것이었다.
오른쪽 전환('D')이 시계방향, 왼쪽 전환('L')이 반시계방향을 뜻한다.
그리고 상하좌우 이동에서, 상(0), 우(1), 하(2), 좌(3)이라고 하면
즉, 현재 방향 상태를 숫자로 표현하고, 그다음 바뀌게 될 방향을 주어진 방향 전환 조건에 맞게 +1 또는 -1 해주면 된다.
추가로, 방향을 바꾸어야 할 시간인지 입력받은 부분을 딕셔너리에 저장한다.
키 / 밸류 를 각각 시간 / 방향으로 저장한다.
반복문을 돌 때마다 딕셔너리를 확인하며 현재 시간이 딕셔너리에 키 값으로 있는지 없는지 확인하고, 있다면 direction을 위의 회전에 따라 갱신해주도록 한다.
6 이동 가능 확인
벽에 부딪히거나, 자기 자신의 몸과 부딪히면 이동할 수 없으므로 반복을 종료한다.
x < 0 or x >= N or y < 0 or y >= N
이면 벽에 부딪히고
board[y][x] == 1
이면 해당 위치에 뱀의 몸이 있다는 뜻이므로 그 좌표로 이동하면 자신의 몸과 부딪힌다.
위의 조건이 아닌 경우에 대해서만 반복한다.
from collections import deque
N = int(input())
K = int(input())
board = [[0] * N for _ in range(N)]
for _ in range(K):
i, j = map(int, input().split())
board[i-1][j-1] = 2 # 행열 인덱스 -1씩 해줘야 함, 사과의 위치 2로 표현
direction_dict = {}
L = int(input())
for _ in range(L):
a, b = input().split()
direction_dict[int(a)] = b
# 상(0), 우(1), 하(2), 좌(3) 이동 : graph[ny][nx] 기준
dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]
direction = 1 # 처음 뱀 이동방향은 오른쪽
time = 0 # 게임 시간
board[0][0] = 1 # 처음 뱀의 위치 1로 표현
nx, ny = 0, 0 # 뱀의 머리 위치
q = deque()
q.append((ny, nx))
def change(d, c):
if c == 'D':
d = (d + 1) % 4
else: # c == 'L':
d = (d - 1) % 4
return d
while True:
time += 1
nx = nx + dx[direction]
ny = ny + dy[direction]
if nx < 0 or nx >= N or ny < 0 or ny >= N:
break
if board[ny][nx] == 1:
break
elif board[ny][nx] == 2: # 사과가 있다면
# board[ny][nx] = 0 # 사과 없애고
board[ny][nx] = 1
q.append((ny, nx))
elif board[ny][nx] == 0: # 사과가 없다면
ey, ex = q.popleft()
board[ey][ex] = 0 # 꼬리 자리는 다시 0으로
board[ny][nx] = 1
q.append((ny, nx))
if time in direction_dict.keys():
direction = change(direction, direction_dict[time]) # <- 키 값을 통해 벨류 값 구하고(d인지 l인지) 같이 인자 전달)
# print(q, time, direction)
print(time)
다만 필요없는 변수도 있고, 노가다 구현 부분이 있어 윗코드를 참고해주세요.
from collections import deque
N = int(input())
K = int(input())
board = [[0] * N for _ in range(N)]
for _ in range(K):
i, j = map(int, input().split())
board[i-1][j-1] = 2 # 행열 인덱스 -1씩 해줘야 함, 사과의 위치 2로 표현
change = []
L = int(input())
for _ in range(L):
a, b = input().split()
change.append((int(a), b))
time = 0 # 게임 시간
size = 1 # 뱀 크기
board[0][0] = 1 # 처음 뱀의 위치 1로 표현
# 순서대로 좌 우 하 상 이동 : graph[ny][nx] 기준
dx = [-1, 1, 0, 0]
dy = [0, 0, -1, 1]
# case 1 : 좌, 2 : 우, 3 : 하, 4 : 상 이동
direction = 2 # 처음 뱀 이동방향은 오른쪽
nx, ny = 0, 0 # 뱀의 머리 위치 - 따로 표기할 필요가 있을까? 그냥 그래프에서 값을 1이 아닌 다른 값으로 해도 될 것 같음
ex, ey = nx, ny # 뱀의 꼬치 위치 - 처음에는 모두 0
change_time = 0
q = deque()
q.append((ny, nx))
while True:
# 뱀이 자기자신과 부딪히거나 벽에 부딪히는 경우 break, 그때의 게임 초 return
# 자기자신과 부딪힘 = 머리가 이동한 곳이 이미 값이 1이다.
time += 1
nx = nx + dx[direction - 1]
ny = ny + dy[direction - 1]
# print(nx, ny)
if nx < 0 or nx >= N or ny < 0 or ny >= N:
break
if board[ny][nx] == 1:
break
elif board[ny][nx] == 2: # 사과가 있다면
board[ny][nx] = 0 # 사과 없애고
size += 1
board[ny][nx] = 1
q.append((ny, nx))
elif board[ny][nx] == 0: # 사과가 없다면 <- ㅋㅋ.. nx ny로 씀..
ey, ex = q.popleft()
board[ey][ex] = 0 # 꼬리 자리는 다시 0으로
board[ny][nx] = 1
q.append((ny, nx))
# print(q, time, size)
for i in range(change_time, L):
if time == change[i][0]:
if change[i][1] == 'L': # 좌
if direction == 1: direction = 4
elif direction == 2: direction = 3
elif direction == 3: direction = 1
elif direction == 4: direction = 2
if change[i][1] == 'D': # 우
if direction == 1: direction = 3
elif direction == 2: direction = 4
elif direction == 3: direction = 2
elif direction == 4: direction = 1
change_time += 1
# print(direction)
print(time)
다음 문제는 무엇을 풀까요