import sys from collections import deque def input(): return sys.stdin.readline().rstrip() def island_bfs(x,y): queue = deque() queue.append((x,y)) visited[x][y] = True island_check[x][y] = island_cnt temp = [(x,y)] while queue: x,y = queue.popleft() for i in range(4): nx = x + dx[i] ny = y + dy[i] if 0<=nx<N and 0<=ny<N: if not visited[nx][ny] and arr[nx][ny]: visited[nx][ny] = True island_check[nx][ny] = island_cnt queue.append((nx,ny)) temp.append((nx,ny)) island_list.append(temp) N = int(input()) arr = [list(map(int,input().split())) for _ in range(N)] visited = [[False for _ in range(N)] for _ in range(N)] island_list = [] island_check = [[0 for _ in range(N)] for _ in range(N)] island_cnt = 1 dx = [-1,0,1,0] dy = [0,-1,0,1] for x in range(N): for y in range(N): if arr[x][y] and not visited[x][y]: island_bfs(x,y) island_cnt += 1 result = float('inf') for island_num in range(len(island_list)): queue = deque(island_list[island_num]) visited = [[0 for _ in range(N)] for _ in range(N)] dis = 1 while queue: q_size = len(queue) flag = False for _ in range(q_size): x,y = queue.popleft() for i in range(4): nx = x + dx[i] ny = y + dy[i] if 0<=nx<N and 0<=ny<N: if island_check[nx][ny] != island_num+1 and not visited[nx][ny]: visited[nx][ny] = dis queue.append((nx,ny)) if island_check[nx][ny]: result = min(result,dis-1) flag = True break if flag: break if flag: break dis += 1 print(result)
가장 첫 풀이는 직관적으로 푼 방식으로 각 섬들을 번호를 마킹해주고,
한 섬의 있는 위치에서 다른 섬에 도착하는 최단 거리를 구해주는 방식이다.
import sys from collections import deque def input(): return sys.stdin.readline().rstrip() def island_bfs(x,y): queue = deque() queue.append((x,y)) visited[x][y] = True island_check[x][y] = island_cnt temp = [(x,y)] while queue: x,y = queue.popleft() bridge_queue.append((x,y,island_cnt,0)) for i in range(4): nx = x + dx[i] ny = y + dy[i] if 0<=nx<N and 0<=ny<N: if not visited[nx][ny] and arr[nx][ny]: visited[nx][ny] = True island_check[nx][ny] = island_cnt queue.append((nx,ny)) temp.append((nx,ny)) island_list.append(temp) def bfs(): global result while bridge_queue: x,y,island_num,dis = bridge_queue.popleft() for i in range(4): nx = x + dx[i] ny = y + dy[i] if 0<=nx<N and 0<=ny<N: if island_check[nx][ny] == island_num: continue if result <= distance_list[nx][ny]: return if not distance_list[nx][ny]: distance_list[nx][ny] = dis + 1 island_check[nx][ny] = island_num bridge_queue.append((nx,ny,island_num,dis+1)) else: if result > distance_list[nx][ny] + distance_list[x][y]: result = distance_list[nx][ny] + distance_list[x][y] N = int(input()) arr = [list(map(int,input().split())) for _ in range(N)] visited = [[False for _ in range(N)] for _ in range(N)] island_list = [] island_check = [[0 for _ in range(N)] for _ in range(N)] island_cnt = 1 dx = [-1,0,1,0] dy = [0,-1,0,1] bridge_queue = deque() for x in range(N): for y in range(N): if arr[x][y] and not visited[x][y]: island_bfs(x,y) island_cnt += 1 result = float('inf') distance_list = [[0 for _ in range(N)] for _ in range(N)] bfs() print(result)
이 방식은 좀 더 빨리 풀 수 잇는 방식으로 위에서는 1섬마다 전부 초기화를 하고, 매번 구하는것에 반해
이 방식은 모든 섬에서 bfs를 동시에 시작하는 것이다.
만약 초기 상태의 점을 방문하게 되면, 해당 위치까지의 거리를 distance_list에 넣어주고, island_check에 해당 위치가 어느 섬에서 왔는지 마킹을 해준다.
그리고 만약 초기화 된 값이 아닌 이미 있는 값이라면, 비교를 해서 현재 위치의 distance_list[x][y] 와 distance_list[nx][ny]를 더한 값이 더 작으면 갱신을 해준다.
그리고 result가 distance_list[nx][ny]보다 작을 시에는 더 갱신할 경우의 수가 없으므로 함수를 종료해준다.
'알고리즘 > 백준' 카테고리의 다른 글
[BOJ/백준] 23289 온풍기 안녕! (0) | 2021.10.25 |
---|---|
[BOJ/백준] 1958 LCS 3 (0) | 2021.09.28 |
[BOJ/백준] 1943 동전 분배 (0) | 2021.09.03 |
[BOJ/백준] 2143 두 배열의 합 (0) | 2021.09.03 |
[BOJ/백준] 1823 수확 (0) | 2021.09.03 |