백준 2589 보물섬 - 그래프 탐색 연습

GUNHEE LEE·2023년 9월 14일
0

보물섬

입력:
세로 가로
보물섬 지도
출력:
최단 거리로 이동하는 시간

입력 예시)
5 7
WLLWWWL
LLLWLLL
LWLWLWW
LWLWLLL
WLLWLWW

우선 육지로 이동할 수 있는 경로를 찾는 방법
1. 모든 원소 가보기
2. 섬이면 상하좌우 이동
3. bfs로 결정되는 시간을 ans=[]에 저장한다.

  • 예시의 경우 좌측의 그래프는 깊이 6칸, 7칸이다. 각 그래프에서 최단거리로 이동하는 방법은 뭘까?

  • 특이한 점은 왼쪽 그래프 첫 번째 노드에서 깊이는 6인데, 정답 노드에서 측정되는 깊이는 8이다. 최단거리를 무시하고, 최장거리만 생각해보면, 가장 긴 거리의 노드는 깊이값이 최대가 되는 노드 위치가 된다.

  • 그럼 bfs로 탐색되는 탐색에서 깊이의 최댓값을 갱신하면서 모든 원소를 탐색하면 깊이의 최댓값을 구할 수 있다.

  • 노드마다 bfs의 깊이정보를 저장해둔다.
    W66WWWW7
    6...
    8WLWLLL
    W8L
    그래서 이걸로 어떻게 구합니까
    아니 어처피 bfs로 탐색하면 최단거리가 나온다. 육지로 갈 수 있는 모든 노드에서 최단거리가 최대인 지점에 보물이 심어질 수 밖에 없다. 그 말은 곧 뭐다. 그래프에서 최대 깊이를 구하면 된다. 걍 이게 끝이었음. 애초에 "최단거리를 최장시간으로 간다" == "bfs(최단거리)로 깊이가 젤 멀리 있는 지점으로 간다"인 것. 그러면 모든 노드를 탐색하면서 깊이가 커질 때마다 최대 깊이를 업데이트해주고 마지막에 최대 깊이출력해주면 된다.

  • 최단거리 라는 단어에 꽂혀서 좀 헤멨다.

bfs에서 가장 큰 깊이를 리턴하게 하는 방법
-> 큐에 삽입할 때 깊이값을 1 늘려준 상태로 추가 삽입한다.
-> popleft 할 때마다 max_depth를 갱신한다.
-> 처음에 i j 0 이 들어감 -> popleft 하고 상하좌우 움직임 -> 움직이 수 있으면 해당 ni, nj, 1로 저장 -> 다시 popleft 이때 max_depth = max(max_depth, depth)로 깊이가 유지되면서 순회하도록 저장한다.

(+) visited를 사용하지 않고 풀었지만 처음에 틀렸다. L이라고 바로 넘어갈 수 있는게 아니므로 visited 방문 여부도 동시에 확인하도록 하자.


시간초과가 떴다.
-> 모든 L에 대해서 bfs를 돌리면 시간초과 난다.
-> L을 선택적으로 bfs에 돌려야 한다.
-> 그럼 무슨 조건을 추가하냐
=> 내 양 옆, 위 아래가 땅인 경우, 그 땅에서 출발할 때 반드시 더 긴 시간이 걸리므로 해당 땅은 탐색하지 않는다.

from collections import deque
import sys
input = sys.stdin.readline
N, M = map(int, input().split())
graph = [list(input().rstrip()) for _ in range(N)]
ans = 0


def bfs(i, j):
    q = deque([])
    q.append([i, j, 0])  # 찾은 섬부터 시작
    visited = [[False]*M for _ in range(N)]
    max_depth = 0
    dx = [0, 0, -1, 1]
    dy = [1, -1, 0, 0]
    while q:
        ci, cj, depth = q.popleft()
        visited[ci][cj] = True
        max_depth = max(max_depth, depth)
        for dir in range(4):
            ni, nj = ci+dx[dir], cj+dy[dir]
            # 이동이 되면
            if 0 <= ni < N and 0 <= nj < M and graph[ni][nj] == 'L' and not visited[ni][nj]:
                q.append([ni, nj, depth+1])
                visited[ni][nj] = True
    return max_depth


for i in range(N):
    for j in range(M):
        if graph[i][j] == 'L':
            if 0 <= i-1 and i+1 < N:
                if graph[i-1][j] == 'L' and graph[i+1][j] == 'L':
                    continue
            if 0 < j-1 and j+1 < M:
                if graph[i][j-1] == 'L' and graph[i][j-1] == 'L':
                    continue
            ans = max(ans, bfs(i, j))

print(ans)
코드를 입력하세요


단순 bfs인데 검사 조건과 깊이 탐색에서 헤멨다. 문제 이해도 오래 걸리고. 조금 까다로웠다.

profile
새싹 개발자

0개의 댓글