프로그래머스 게임 맵 최단거리(Python)

박노정·2021년 6월 8일
0

알린이의 알고리즘

목록 보기
3/15

https://programmers.co.kr/learn/courses/30/lessons/1844

ROR 게임은 두 팀으로 나누어서 진행하며, 상대 팀 진영을 먼저 파괴하면 이기는 게임입니다. 따라서, 각 팀은 상대 팀 진영에 최대한 빨리 도착하는 것이 유리합니다.
게임 맵의 상태 maps가 매개변수로 주어질 때, 캐릭터가 상대 팀 진영에 도착하기 위해서 지나가야 하는 칸의 개수의 최솟값을 return 하도록 solution 함수를 완성해주세요. 단, 상대 팀 진영에 도착할 수 없을 때는 -1을 return 해주세요.

제한사항
maps는 n x m 크기의 게임 맵의 상태가 들어있는 2차원 배열로, n과 m은 각각 1 이상 100 이하의 자연수입니다.
n과 m은 서로 같을 수도, 다를 수도 있지만, n과 m이 모두 1인 경우는 입력으로 주어지지 않습니다.
maps는 0과 1로만 이루어져 있으며, 0은 벽이 있는 자리, 1은 벽이 없는 자리를 나타냅니다.
처음에 캐릭터는 게임 맵의 좌측 상단인 (1, 1) 위치에 있으며, 상대방 진영은 게임 맵의 우측 하단인 (n, m) 위치에 있습니다.

def solution(maps):
    dx = [1,-1,0,0]
    dy = [0,0,-1,1]
    answer=123123123123123123123123
    def search(x,y,times):
        nonlocal answer
        if x == len(maps[0])-1 and y == len(maps)-1:
            if times < answer:
                answer = times
        for i in range(len(dx)):
            nx = x + dx[i]
            ny = y + dy[i]
            if 0 <= nx < len(maps[0]) and 0 <= ny < len(maps) and maps[ny][nx]:
                maps[y][x] = 0
                search(nx,ny,times+1)
        
    
    search(0,0,1)
    if answer == 123123123123123123123123:
        return -1
    else:
        return answer

dfs로 풀려했다. 정확성에서 몇문제틀렸고 깊이가 너무 깊은지 효율성은 런타임 에러가 떴다.
그래서 좀 더 익숙하고 자신있는 bfs로 전향했다.

from collections import deque
def solution(maps):
    dx = [1,-1,0,0]
    dy = [0,0,-1,1]
    n = len(maps)
    m = len(maps[0])
    answer= 0
    Q = deque()
    Q.append((0,0,1))
    while Q:
        y,x,answer = Q.popleft()
        maps[y][x] = 0
        for i in range(len(dx)):
            ny = y + dy[i]
            nx = x + dx[i]
            if nx == m-1 and ny == n-1:
                return answer + 1
            elif 0 <= nx < m and 0 <= ny < n and maps[ny][nx]:
                Q.append((ny,nx,answer+1))
            

    
    return -1


정확성은 다맞지만 효율성에서 실패했다. 왜지...?
아마도 이중으로 돌 수 있어서 그런것같다.
Q에 넣어놓은 좌표를 방문하기 전에 또 넣고,,,
그래서 방문예정인 좌표도 0으로 만들어 방문을 못하도록 했다.
visited라는 방문체크용 list를 만들 수도 있었지만 만들고 싶지 않았다. 그래서 안 만들고 처리하기위해 안간힘을 썼다
성공했다.

from collections import deque
def solution(maps):
    dx = [1,-1,0,0]
    dy = [0,0,-1,1]
    n = len(maps)
    m = len(maps[0])
    answer= 1
    Q = deque()
    Q.append((0,0,answer))
    while Q:
        y,x,answer = Q.popleft()
        maps[y][x] = 0
        for i in range(len(dx)):
            ny = y + dy[i]
            nx = x + dx[i]
            if nx == m-1 and ny == n-1:
                return answer + 1
            elif 0 <= nx < m and 0 <= ny < n and maps[ny][nx]:
                Q.append((ny,nx,answer+1))
            	maps[ny][nx] = 0

    
    return -1
profile
성장스택 쌓고있는 개발자🏋

1개의 댓글

comment-user-thumbnail
2023년 4월 20일

안녕하세요 덕분에 해결했습니다! 근데 방문전인 위치도 미리 0으로 변경(maps[ny][nx] = 0) 함으로써 어떤 로직으로 효율성이 높아지는 것인지 헷갈리는데 알려주실 수 있으신가요?

답글 달기