최민수·2023년 4월 7일
0

알고리즘

목록 보기
50/94
from collections import deque

N = int(input())
K = int(input())
applePos = [list(map(int, input().split())) for i in range(K)]
L = int(input())
dirInfo = [list(input().split()) for i in range(L)]
maps = [[False for i in range(N)] for j in range(N)]


# Termination 조건
def isGameOver():
    x, y = snakePos[0]
    snakeTemp = []
    for i in range(1, len(snakePos)):
        snakeTemp.append(snakePos[i])
    # 벽에 부딪힘
    if x < 0 or x >= N or y < 0 or y >= N:
        return True

    # 자신의 몸과 부딪힘
    for itemX, itemY in snakeTemp:
        if x == itemX and y == itemY:
            return True

    return False


def move():
    global snakePos, curDir, terminate

    headX, headY = snakePos.popleft()
    updateX, updateY = headX, headY
    temp = deque()

    while snakePos:
        temp.append(snakePos.popleft())

    if curDir == "R":
        snakePos.appendleft((headX, headY+1))
        updateY = headY + 1
    elif curDir == "L":
        snakePos.appendleft((headX, headY - 1))
        updateY = headY - 1
    elif curDir == "U":
        snakePos.appendleft((headX - 1, headY))
        updateX = headX - 1
    elif curDir == "D":
        snakePos.appendleft((headX + 1, headY))
        updateX = headX + 1

    temp.appendleft((headX, headY))
    if not checkApple(updateX, updateY):
        if temp:
            lastVal = temp.pop()
            if lastVal == (updateX, updateY):
                terminate = True
    while temp:
        snakePos.append(temp.popleft())


def checkApple(x, y):
    if 0 <= x < N and 0 <= y < N and maps[x][y]:
        maps[x][y] = False
        return True
    return False


def updateDir():
    global curDir, dirCmd

    if dirCmd != "-":
        if curDir == "R":
            if dirCmd == "L":
                curDir = "U"
            else:
                curDir = "D"
        elif curDir == "L":
            if dirCmd == "L":
                curDir = "D"
            else:
                curDir = "U"
        elif curDir == "U":
            if dirCmd == "L":
                curDir = "L"
            else:
                curDir = "R"
        elif curDir == "D":
            if dirCmd == "L":
                curDir = "R"
            else:
                curDir = "L"


index, timeCount = 0, 0
snakePos = deque()
curDir = "R"
dirCmd = "-"
terminate, isChecked = False, True

for idx, (itemRow, itemCol) in enumerate(applePos):
    applePos[idx] = (itemRow-1, itemCol-1)
    maps[itemRow-1][itemCol-1] = True

snakePos.append((0, 0))

while True:
    timeCount += 1
    move()
    # 방향 전환
    if isChecked and timeCount == int(dirInfo[index][0]):
        dirCmd = dirInfo[index][1]
        updateDir()
        index += 1
        if index >= len(dirInfo):
            isChecked = False

    if terminate or isGameOver():
        break

print(timeCount)

구현 로직이 생각보다 복잡하지는 않았다. 하지만 두 가지 이유로 풀이 시간이 엄청나게 걸려 버렸다.

첫번째는 문제의 조건과 입력이 1행 1열 부터 시작했고 그렇게 입력을 줬다는 점이다. 나는 당연하게도 0행 0열 부터로 생각하고 코드를 짰는데 입력이 1씩 커졌고 예외 처리도 그렇게 했으니 당연히 답이 틀릴 수 밖에 없다.

두번째는 위 문제보다 더 중요한 문제이다.

파이썬에서 for문 안에 iterable 한 객체를 순회할 때 쓰는 변수global 변수와 이름이 중복되면 이게 생각치도 못하게 값이 바뀌면서 꼬여버린다.

함수 안에서의 local 변수global 변수만 구별해주면 되는 것으로 알았는데 반복문에서 순회용으로 쓰는 변수까지 신경 써야 한다는 사실은 정말 새로 알았다.

예를 들면 아래 코드와 같다.

idx = 0

for idx, (itemRow, itemCol) in enumerate(applePos): 
    ... # 여기 반복문에서 `idx` 값이 계속 갱신되고 있음
 
 ...
 
if visited[idx]: # `idx`에 이상한 값이 들어가 있음
	... 

문제 출처:https://www.acmicpc.net/problem/3190

profile
CS, 개발 공부기록 🌱

0개의 댓글