baby_ohgu 2021. 1. 27. 22:44

www.acmicpc.net/problem/3190

 

3190번: 뱀

 'Dummy' 라는 도스게임이 있다. 이 게임에는 뱀이 나와서 기어다니는데, 사과를 먹으면 뱀 길이가 늘어난다. 뱀이 이리저리 기어다니다가 벽 또는 자기자신의 몸과 부딪히면 게임이 끝난다. 게임

www.acmicpc.net

 

문제풀이

N, K, L : 입력값

command : 명령

d : 방향

time : 현재 시간

cmd_idx : command 리스트의 원소 탐색을 위한 인덱스

 

특별한 알고리즘 필요없이 단순히 주어진 조건대로 잘 구현(?) 하기만 하면 해결할 수 있는 문제이다. 한 가지 주의할 것이, 사과가 없는 빈 공간으로 뱀의 머리가 이동할때, 몸 길이가 변하지 않는 것이다. 이 부분만 주의하면 문제없이 해결할 수 있다.

 

board[x] = 0 : 빈 공간

board[x] = 1 : 현재 뱀의 몸 중 일부가 있는 곳

board[x] = 2 : 사과가 있는 공간

d = 0 : 하, 1 : 좌, 2 : 상, 3 : 우

 

1. 입력을 통해 사과가 있는 곳의 값을 2로 변경한다.

 

2. (0,0) 부터 시작해서 오른쪽 방향(d = 3)으로 탐색을 시작한다.

- 빈 공간일 경우(board[x] == 0), 몸 전체를 이동한다.(꼬리가 있는 곳 제외, 새롭게 머리가 이동한 곳 추가)

- 사과가 있는 공간일 경우(board[x] == 2), 꼬리를 없애지 않고 새롭게 머리가 이동한 곳을 추가한다.

- 벽 이거나, 이미 뱀의 일부(board[x] == 1)일 경우 종료한다.

 

3. 2의 과정을 반복하면서 시간을 1씩 증가하면서, 명령어의 시간과 일치할 경우 명령을 실행한다.

- 명령어가 'D'일 경우 시계 방향으로 변경 ( d = (d + 1) % 4 )

- 명령어가 'L'일 경우 반시계 방향으로 변경 ( d = (d - 1) % 4 )

 

q에서 항상 머리가 있는 곳의 좌표를 pop하였는데, 새롭게 이동하는 곳이 빈 공간일 경우 앞에서 뺀 머리가 있던 곳의 좌표를 다시 q에 넣어주는 것에서 헷갈렸다.

 

코드

import sys
from collections import deque

dx = [1, 0, -1, 0]
dy = [0, -1, 0, 1]

def solution(x, y):
    board[x][y] = 1
    d = 3
    q = deque([(x, y)])
    time = 0
    cmd_idx = 0
    while q:
        x, y = q.pop()
        # 아직 실행하지 않은 명령어가 남아있을 경우
        if cmd_idx < len(command):
            t, c = command[cmd_idx]
            # 시간이 일치하면 방향 변경
            if time == t:
                if c == 'D':
                    d = (d + 1) % 4
                else:
                    d = (d - 1) % 4
                cmd_idx += 1
        nx, ny = x + dx[d], y + dy[d]
        if 0 <= nx < N and 0 <= ny < N:
            # 새롭게 이동할 곳이 이미 뱀의 일부일 경우 종료
            if board[nx][ny] == 1:
                return time + 1
            # 새롭게 이동할 곳이 사과일 경우
            elif board[nx][ny] == 2:
                # 앞에서 pop 하였던 이전 뱀의 머리 좌표 추가
                q.append((x, y))
                # 새롭게 이동할 뱀의 머리 좌표 추가
                q.append((nx, ny))
                board[nx][ny] = 1
            # 새롭게 이동할 곳이 빈 공간일 경우
            else:
                # 머리를 제외한 뱀의 꼬리가 존재할 경우
                if q:
                    # 꼬리 제거
                    tx, ty = q.popleft()
                    board[tx][ty] = 0
                    # 앞에서 pop 하였던 이전 뱀의 머리 좌표 추가 => 뱀의 몸 길이 유지
                    q.append((x, y))
                # 머리와 꼬리가 일치할 경우 이전 뱀의 머리 좌표 추가할 필요 X => 밑에서 새롭게 이동할 머리 좌표를 추가하기 때문
                else:
                    board[x][y] = 0
                # 머리는 반드시 한칸 이동
                q.append((nx, ny))
                board[nx][ny] = 1
        # 이동할 곳이 벽일 경우 종료
        else: return time + 1
        time += 1

if __name__ == '__main__':
    N = int(input())
    board = [[0] * N for _ in range(N)]
    K = int(input())
    for _ in range(K):
        r, c = map(int, sys.stdin.readline().split())
        board[r - 1][c - 1] = 2
    L = int(input())
    command = []
    for _ in range(L):
        a, b = map(str, sys.stdin.readline().split())
        command.append((int(a), b))
    print(solution(0, 0))

 

결과

 

문제풀이나 코드에서 이상한 부분 지적은 언제나 환영합니다!