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 |