Processing math: 100%

ABOUT ME

Today
Yesterday
Total
  • [Python 3] BOJ - 17090 "미로 탈출하기"
    BOJ 2021. 10. 15. 21:57

     # 문제 링크

    https://www.acmicpc.net/problem/17090

     

    17090번: 미로 탈출하기

    크기가 N×M인 미로가 있고, 미로는 크기가 1×1인 칸으로 나누어져 있다. 미로의 각 칸에는 문자가 하나 적혀있는데, 적혀있는 문자에 따라서 다른 칸으로 이동할 수 있다. 어떤 칸(r, c)에 적힌 문

    www.acmicpc.net

     

     # 풀이

     개인적으로 이 문제의 핵심은 다이나믹 프로그래밍이라고 생각한다. 상태 공간을 현재 (x, y)일 때 밖으로 나갈 수 있는지 여부로 정의한다.

    <그림 1. 예제 4의 경우>

     위 그림 1은 예제 4의 경우를 나타낸 그림이다. 빨간색이 현재 위치, 파란색 위치가 다음 위치일 때 상태이다. 만일 현재 위치를 한번도 방문하지 않는다면 -1, 처음 방문한다면 0으로 초기화한다. 만일 범위 밖으로 나간다면 1을 리턴함으로서 전체 경로를 1로 변경한다. 마지막의 경우는 이미 방문했으나 밖으로 나갈 수 없기 때문에 상태 공간의 탐색을 종료한다.

     따라서, 현재 (0, 0)으로 이어지는 모든 경로는 밖으로 나갈 수 있는지 없는지의 여부가 갱신되었기 때문에 방문 하지 않은 위치인 (0, 3)에서 다시 상태 공간을 탐색한다.

    <그림 2. 예제 4의 경우>

     위 그림 2는 그림 1과 달리 밖으로 나가는 경로를 찾은 경우이다. 만일 현재의 위치가 밖이라면 1을 리턴하여 현재 위치까지 오기 위한 모든 경로에 1로 갱신한다. 따라서 점화식은 아래와 같다. dp[x][y]=max(dp[x][y], value) if outside, val=1 else val=0) 따라서, 현재 방문하지 않았다면 리턴값이 0이 아닌 블록을 모두 세어주고, 방문했다면 상태 배열값이 0이 아닌 블록을 모두 세어주면 정답을 구할 수 있다.

     

     # 코드

    import sys
    
    # 재귀깊이 해제
    sys.setrecursionlimit(600000)
    
    # go : 현재 위치가 (i, j)일 때 밖으로 나가는 경로의 일부라면 1, 아니면 0을 리턴하는 함수
    def go(i, j):
        # Base case : 밖으로 나가는 경우
        if i < 0 or i > n - 1 or j < 0 or j > m - 1:
            return 1
        # Memoization
        if dp[i][j] != -1:
            return dp[i][j]
        dp[i][j] = 0
        # 점화식
        dp[i][j] = max(dp[i][j], go(i + cache[arr[i][j]][0], j + cache[arr[i][j]][1]))
        return dp[i][j]
    
    # 입력부
    n, m = map(int, sys.stdin.readline().split())
    arr = [list(sys.stdin.readline().rstrip()) for _ in range(n)]
    
    # dp : 2차원 상태 공간 배열
    dp = [[-1] * m for _ in range(n)]
    
    # cache : 현재 위치가 가리키는 방향을 key, 그 때 가야할 칸 수를 value로 갖는 dictionary
    cache = {'L' : (0, -1), 'R' : (0, 1), 'U' : (-1, 0), 'D' : (1, 0)}
    ans = 0
    
    for i in range(n):
        for j in range(m):
            # 아직 방문하지 않은 경우
            if dp[i][j] == -1:
                # 밖으로 갈 수 있다면 정답 증가
                if go(i, j) != 0:
                    ans += 1
            # 방문했고 밖으로 나갈 수 있는 경우 정답 증가
            elif dp[i][j] == 1:
                ans += 1
                
    # 정답 출력
    print(ans)

    댓글

Designed by Tistory.