From 4877bcb1a1d02beabaaf7c7e5553a47150843d13 Mon Sep 17 00:00:00 2001 From: Sumin Date: Wed, 16 Aug 2023 12:55:01 +0900 Subject: [PATCH 1/3] =?UTF-8?q?Create=20=EB=B6=88!=20sumin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "BOJ/\353\266\210!/sumin.py" | 70 ++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) create mode 100644 "BOJ/\353\266\210!/sumin.py" diff --git "a/BOJ/\353\266\210!/sumin.py" "b/BOJ/\353\266\210!/sumin.py" new file mode 100644 index 00000000..2d6aeba2 --- /dev/null +++ "b/BOJ/\353\266\210!/sumin.py" @@ -0,0 +1,70 @@ +""" +풀이시간: 35분 + + +1 ≤ R, C ≤ 1000 +- R: 미로 행의 개수 +- C: 열의 개수 + + +이 문제의 경우 불과 지훈이가 동시에 이동하기 때문에, 이 처리를 어떻게 해줄 것인지가 관건인 문제다. +하지만, 불은 1분에 인접한 네 방향으로 모두 이동지만, 지훈이의 경우 한 칸 밖에 이동하지 못한다. +따라서 둘에 대해 각각의 BFS 확인해 각 칸에 도착하는데 걸리는 이동 시간을 확인하면 된다. +불의 전파시간에 대한 BFS를 먼저 확인 후, 지훈이의 이동에 대한 BFS를 돌면 되는데 이 때 다음의 조건을 확인하면 된다. +- 지훈이가 도착할 예정시간보다 불이 해당 칸에 전파되는 시간이 더 짧은 경우(지훈이가 도착하면 이미 불이 붙어있기 때문에 탈출 실패) + +<시간복잡도> +BFS 시간복잡도: O(R*C), 최대 1,000,000번 연산 +""" +import sys +input = sys.stdin.readline +from collections import deque + +# 행과 열 입력받기 +r, c = map(int, input().split()) + +# 상하좌우 방향 +dx = [-1, 1, 0, 0] +dy = [0, 0, -1, 1] + +fire = [[-1] * c for _ in range(r)] # 불의 전파 시간 +jihoon = [[-1] * c for _ in range(r)] # 지훈이의 이동 시간 + + +q1 = deque() # 불의 전파에 대한 BFS 돌기 위한 큐 +q2 = deque() # 지훈이 이동에 대한 BFS 돌기 위한 큐 +board = [list(input()) for _ in range(r)] # 미로 +for i in range(r): + for j in range(c): + if board[i][j] == 'F': # 불 + q1. append((i, j)) + fire[i][j] = 0 + elif board[i][j] == 'J': # 지훈 + q2.append((i, j)) + jihoon[i][j] = 0 + + +# 불에 대한 BFS +while q1: + x, y = q1.popleft() + for i in range(4): # 현재위치에서 상하좌우 위치 확인 + nx, ny = x+dx[i], y+dy[i] + if nx < 0 or nx >= r or ny < 0 or ny >= c: continue # 미로의 범위를 벗어난 경우 무시 + if fire[nx][ny] >= 0 or board[nx][ny] == '#': continue # 이미 방문한 노드이거나, 벽인 경우 무시 + fire[nx][ny] = fire[x][y] + 1 + q1.append((nx, ny)) + +# 지훈이에 대한 BFS +while q2: + x, y = q2.popleft() + for i in range(4): + nx, ny = x+dx[i], y+dy[i] + if nx < 0 or nx >= r or ny < 0 or ny >= c: # 범위를 벗어났다는 것은 탈출에 성공했다는 의미 + print(jihoon[x][y]+1) # 탈출한 시간 출력 + exit() + if jihoon[nx][ny] >= 0 or board[nx][ny] == '#': continue + if fire[nx][ny] != -1 and fire[nx][ny] <= jihoon[x][y]+1: continue # 불의 전파 시간을 조건에 추가 (지훈이의 도착시간보다 불이 먼저 붙을 곳) + jihoon[nx][ny] = jihoon[x][y]+1 + q2.append((nx, ny)) + +print("IMPOSSIBLE") # 탈출에 실패 \ No newline at end of file From 9735042fa8c8e76cac206156aa549d454680bab5 Mon Sep 17 00:00:00 2001 From: Sumin Date: Wed, 16 Aug 2023 14:32:22 +0900 Subject: [PATCH 2/3] =?UTF-8?q?Create=20=EB=B9=99=EC=82=B0=20sumin.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "BOJ/\353\271\231\354\202\260/sumin.py" | 75 +++++++++++++++++++++++++ 1 file changed, 75 insertions(+) create mode 100644 "BOJ/\353\271\231\354\202\260/sumin.py" diff --git "a/BOJ/\353\271\231\354\202\260/sumin.py" "b/BOJ/\353\271\231\354\202\260/sumin.py" new file mode 100644 index 00000000..60cf1808 --- /dev/null +++ "b/BOJ/\353\271\231\354\202\260/sumin.py" @@ -0,0 +1,75 @@ +""" +풀이시간: 40분 + + +- n: 행의 개수(3 <= m <= 300) +- m: 열의 개수(3 <= m <= 300) + + +1. 각 빙산 좌표에서 BFS를 통해 빙산이 몇 칸의 인접한 바다가 있는 만큼 빙산을 녹여준다. +2. 빙산이 모두 녹을 때까지 또는 빙산이 두 개 이상으로 분리될 때까지 시간을 증가시키며 반복한다. + +<시간복잡도> +O(k * n * m) +- k: 빙산의 개수 +연산횟수를 계산해보면 최악의 경우 9억까지 가능한데, 데이터(테스트케이스)가 부족하다는 생각이 든다. +""" +import sys + +input = sys.stdin.readline +from collections import deque + + +# 동서남북 +dx = [0, 0, 1, -1] +dy = [1, -1, 0, 0] + +# 행, 열의 개수 +n, m = map(int, input().split()) +graph = [list(map(int, input().split())) for _ in range(n)] # 그래프(빙산과 바다 정보) +ice = set() # 빙산 좌표 + +for i in range(n): + for j in range(m): + if graph[i][j] != 0: # 빙산 + ice.add((i, j)) + + +def bfs(x, y): # 빙산 좌표 BFS + q = deque([(x, y)]) + visited[x][y] = True + + while q: + x, y = q.popleft() + for i in range(4): # 인접한 네 방향을 모두 살펴봄 + nx, ny = x + dx[i], y + dy[i] + if not visited[nx][ny]: # 아직 방문하지 않은 칸 + if ( + graph[nx][ny] == 0 and graph[x][y] != 0 + ): # 인접한 칸이 바다(0)이고, 현재 위치는 빙산일 때 + graph[x][y] -= 1 # 빙산을 1 녹임 + if graph[nx][ny] != 0: # 인접한 칸이 빙산일 경우 -> 방문처리 후 큐에 추가 + visited[nx][ny] = True + q.append((nx, ny)) + if graph[x][y] == 0: # 바다에 의해 다 녹아버리는 빙산 좌표를 제거 + ice.remove((x, y)) + + +year = 0 # 빙산이 분리되는 최초의 시간(년) +while True: + cnt = 0 # 분리된 빙산의 수 + visited = [[False] * m for _ in range(n)] # 방문처리 배열 + ice_berg = ice.copy() + for r, c in ice_berg: # 빙산에 대해 BFS + if graph[r][c] != 0 and not visited[r][c]: + bfs(r, c) + cnt += 1 + # 빙산이 두 개 이상으로 분리된 경우 + if cnt >= 2: + print(year) + break + # 빙산이 분리되지 않은 경우 + if cnt == 0: + print(0) + break + year += 1 From 7b4c2b61998606b42a22c93fda786690500c517c Mon Sep 17 00:00:00 2001 From: Sumin Date: Fri, 18 Aug 2023 19:59:22 +0900 Subject: [PATCH 3/3] comment : modify time complexity --- "BOJ/\353\271\231\354\202\260/sumin.py" | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git "a/BOJ/\353\271\231\354\202\260/sumin.py" "b/BOJ/\353\271\231\354\202\260/sumin.py" index 60cf1808..52fa1a4c 100644 --- "a/BOJ/\353\271\231\354\202\260/sumin.py" +++ "b/BOJ/\353\271\231\354\202\260/sumin.py" @@ -10,9 +10,10 @@ 2. 빙산이 모두 녹을 때까지 또는 빙산이 두 개 이상으로 분리될 때까지 시간을 증가시키며 반복한다. <시간복잡도> -O(k * n * m) -- k: 빙산의 개수 -연산횟수를 계산해보면 최악의 경우 9억까지 가능한데, 데이터(테스트케이스)가 부족하다는 생각이 든다. +O(10 * k * n*m) +- 10: 빙산 한 겹이 사라지는데 걸리는 시간 +- k: 빙산의 겹은 최대 100 +- n*m: 빙산 하나에 대한 BFS """ import sys