알고리즘/BFS

[BFS] 백준 - 1261번 알고스팟

코딩균 2021. 9. 13. 21:44
BFS

벽 부시는 것을 최소화 하는 경로를 찾기 위해서 일단은 주변 방들을 탐색하면서 진행하는 것이 좋다고 판단해 BFS를 사용한다. 

 

벽 부시기 횟수 최소화 하기 위한 조건?

1인 방에 가면 벽을 부셔야 하는 횟수가 늘어나기 때문에 0인 방부터 우선으로 검사할 수 있도록 하자

  • 0인 방은 일단 부시기가 안 일어나므로 Queue에서 appendLeft하여 먼저 pop 될 수 있도록 한다
  • 1인 방은 부시기가 일어나므로 Queue에서 append 하여서 pop 우선순위를 뒤로 미룬다
방문 여부 체크

BFS와 Queue를 통해 가장 빠르고 부시는 수를 최소화 할 수 있는 경로로 찾아가기 때문에 한번 방문한 방을 방문처리를 하지 않는다면 다른 노드에서 다시 방문해서 속도가 떨어질 것이라 판단

visited 배열을 따로 생성하지 않고 graph에서 방문이 끝나면 1/0을 -1로 바꾸어 주는 방식을 택함

1차 코드

from collections import deque
import sys
inpurt = sys.stdin.readline

INF = int(1e9)

M, N = map(int, input().split()) # M 가로 크기 / N 세로 크기

graph = [list(map(int, input().rstrip()))for _ in range(N)]
dir_col = [1, 0, -1, 0]
dir_row = [0, 1, 0, -1]


queue = deque()
    
def miro(graph):
    
    queue.append([0, 0, 0])
    
    while len(queue) != 0:
        
        pop_room = queue.popleft()
        graph[pop_room[0]][pop_room[1]] = -1  # 문제라고 판단된 부분

        if pop_room[1] == M-1 and pop_room[0] == N-1:
            print(pop_room[2])
            return

        for i in range(0, 4):
            n_row = pop_room[0] + dir_row[i]
            n_col = pop_room[1] + dir_col[i]
            if (0<= n_col <M) and (0<= n_row <N) and graph[n_row][n_col] != -1:
                if graph[n_row][n_col] == 1:
                    queue.append([n_row, n_col, pop_room[2]+1]) 
                elif graph[n_row][n_col] == 0:
                    queue.appendleft([n_row, n_col, pop_room[2]])


miro(graph)
문제점

시간초과

큐에서 꺼낼 때만 visited 처리를 해주는 것이 노드들의 방문수를 증가시키는 것이라 생각하여 코드를 아래와 같이 큐에 넣을 때 visited로 전환하는 방식으로 처리

 

최종 코드

from collections import deque
import sys
inpurt = sys.stdin.readline

INF = int(1e9)

M, N = map(int, input().split()) # M 가로 크기 / N 세로 크기

graph = [list(map(int, input().rstrip()))for _ in range(N)]
dir_col = [1, 0, -1, 0]
dir_row = [0, 1, 0, -1]


queue = deque()
    
def miro(graph):
    
    queue.append([0, 0, 0])
    
    while len(queue) != 0:
        
        pop_room = queue.popleft()
        

        if pop_room[1] == M-1 and pop_room[0] == N-1:
            print(pop_room[2])
            return

        for i in range(0, 4):
            n_row = pop_room[0] + dir_row[i]
            n_col = pop_room[1] + dir_col[i]
            if (0<= n_col <M) and (0<= n_row <N) and graph[n_row][n_col] != -1:
                if graph[n_row][n_col] == 1:
                    graph[n_row][n_col] = -1  # 큐에 집어 넣을 때 방문 처리 진행
                    queue.append([n_row, n_col, pop_room[2]+1]) 
                elif graph[n_row][n_col] == 0:
                    graph[n_row][n_col] = -1 # 큐에 집어 넣을 때 방문 처리 진행
                    queue.appendleft([n_row, n_col, pop_room[2]])


miro(graph)