ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 14497번 주난의 난
    Algorithm Study/Python 2021. 8. 10. 15:08

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

     

    14497번: 주난의 난(難)

    주난이는 크게 화가 났다. 책상 서랍 안에 몰래 먹으려고 숨겨둔 초코바가 사라졌기 때문이다. 주난이는 미쳐 날뛰기 시작했다. 사실, 진짜로 뛰기 시작했다. ‘쿵... 쿵...’ 주난이는 점프의 파

    www.acmicpc.net

    문제

    주난이는 크게 화가 났다. 책상 서랍 안에 몰래 먹으려고 숨겨둔 초코바가 사라졌기 때문이다. 주난이는 미쳐 날뛰기 시작했다. 사실, 진짜로 뛰기 시작했다.

    ‘쿵... 쿵...’

    주난이는 점프의 파동으로 주변의 모든 친구들을 쓰러뜨리고(?) 누군가 훔쳐간 초코바를 찾으려고 한다. 주난이는 N*M크기의 학교 교실 어딘가에서 뛰기 시작했다. 주난이의 파동은 상하좌우 4방향으로 친구들을 쓰러뜨릴(?) 때 까지 계속해서 퍼져나간다. 다르게 표현해서, 한 번의 점프는 한 겹의 친구들을 쓰러뜨린다. 다음의 예를 보자.

    주난이를 뜻하는 *은 (3, 4)에 있고, 초코바를 가진 학생 #는 (1, 2)에 있다. 0은 장애물이 없는 빈 공간임을 뜻하고, 1은 친구들이 서있음을 의미한다. 다음은 주난이의 점프에 따른 생존(?) 학생들의 변화이다.

    위의 예시에서 주난이는 3번의 점프 만에 초코바를 훔쳐간 범인을 찾아낼 수 있다!

    주난이를 빨리 멈춰야 교실의 안녕을 도모할 수 있다. 주난이에게 최소 점프 횟수를 알려줘서 교실을 지키자.

    입력

    첫째 줄에 주난이가 위치한 교실의 크기 N, M이 주어진다. (1 <= N, M <= 300)

    둘째 줄에 주난이의 위치 x1, y1과 범인의 위치 x2, y2가 주어진다. (1 <= x1, x2 <= N, 1 <= y1, y2 <= M)

    이후 N*M 크기의 교실 정보가 주어진다. 0은 빈 공간, 1은 친구, *는 주난, #는 범인을 뜻한다.

    출력

    주난이가 범인을 잡기 위해 최소 몇 번의 점프를 해야 하는지 출력한다.

     

     

     

    풀이

    1을 만날 때마다 파동이 사라지기 때문에 *까지 도착하기 위해서는 몇 개의 1을 지나야 도착할 수 있는지 확인하면 된다.
    전에 풀이한 알고패스의 벽을 뚫고 지나가는 것과 동일한 방법으로 풀 수 있다.

     

    dist = [[-1 for _ in range(COL)] for _ in range(ROW)]
    dist[start_y-1][start_x-1] = 0

    dist 배열을 이용하여 해당 좌표까지 지나가는 1의 갯수를 계산했다.

     

    direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    
    dq = deque()
    dq.append((start_y-1, start_x-1))
    
    while dq:
        y, x = dq.popleft()
        for i in range(4):
            next_y, next_x = y + direction[i][0], x + direction[i][1]
            if 0 <= next_y < ROW and 0 <= next_x < COL and dist[next_y][next_x] == -1:
                if board[next_y][next_x] == '0':
                    dq.appendleft((next_y, next_x))
                    dist[next_y][next_x] = dist[y][x]
                else:
                    dq.append((next_y, next_x))
                    dist[next_y][next_x] = dist[y][x] + 1

    01 BFS를 이용하여 풀이했다.
    다음 이동할 곳의 좌표가 0인 경우에는 dq의 왼쪽에 삽입해서 먼저 탐색하게하고 1인 경우에는 오른쪽에 삽입해서 0인 경우보다 늦게 탐색하게 하는 것으로 0을 지나가는 경우에 1보다 먼저 *에 도착하게된다.

     

    전체 코드

    import sys
    from collections import deque
    
    ROW, COL = map(int, sys.stdin.readline().split())
    start_y, start_x, end_y, end_x = map(int, sys.stdin.readline().split())
    board = [list(map(str, sys.stdin.readline().strip())) for _ in range(ROW)]
    
    dist = [[-1 for _ in range(COL)] for _ in range(ROW)]
    dist[start_y-1][start_x-1] = 0
    direction = [[1, 0], [-1, 0], [0, 1], [0, -1]]
    
    dq = deque()
    dq.append((start_y-1, start_x-1))
    
    while dq:
        y, x = dq.popleft()
        for i in range(4):
            next_y, next_x = y + direction[i][0], x + direction[i][1]
            if 0 <= next_y < ROW and 0 <= next_x < COL and dist[next_y][next_x] == -1:
                if board[next_y][next_x] == '0':
                    dq.appendleft((next_y, next_x))
                    dist[next_y][next_x] = dist[y][x]
                else:
                    dq.append((next_y, next_x))
                    dist[next_y][next_x] = dist[y][x] + 1
    
    print(dist[end_y-1][end_x-1])

     

    알고패스와 동일한 방법으로 풀이가 가능하기 때문에 로직 구현에는 크게 어려움이 없었는데
    코드의 오타를 찾는데 시간이 많이 걸렸던 문제다.

    'Algorithm Study > Python' 카테고리의 다른 글

    [백준] 2800번 괄호제거  (0) 2021.08.11
    [백준] 16938번 캠프 준비  (0) 2021.08.11
    [백준] 14567번 선수과목  (2) 2021.08.10
    [백준] 1726번 로봇  (0) 2021.07.28
    [백준] 1715번 카드 정렬하기  (0) 2021.07.27

    댓글

From BlackHair