From 9a9fbb894b39c8ee2472ef47f5cea3182e999aa6 Mon Sep 17 00:00:00 2001 From: Woo-Yeol Date: Wed, 16 Aug 2023 14:12:59 +0900 Subject: [PATCH 1/2] =?UTF-8?q?Create=20=EB=B9=99=EC=82=B0=20wooyeol.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "BOJ/\353\271\231\354\202\260/wooyeol.py" | 121 ++++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 "BOJ/\353\271\231\354\202\260/wooyeol.py" diff --git "a/BOJ/\353\271\231\354\202\260/wooyeol.py" "b/BOJ/\353\271\231\354\202\260/wooyeol.py" new file mode 100644 index 00000000..80f6b8a5 --- /dev/null +++ "b/BOJ/\353\271\231\354\202\260/wooyeol.py" @@ -0,0 +1,121 @@ +""" + 빙산 + https://www.acmicpc.net/problem/2573 + + 풀이시간 + 10:33 ~ 14:12 (풀이 실패) + + 접근법 + 무슨 알고리즘으로 풀이 할 수 있을까? bfs + + 시간 초과와 메모리 초과로 실패했습니다. + +""" +import sys +import copy +from collections import deque + +input = sys.stdin.readline + + +def check_cycle(R: int, C: int, start_point: tuple, iceberg_count: int, iceberg: list): + directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) + count: int = 1 + visited = set() + s_queue = deque([start_point]) + + while s_queue: + tx, ty = s_queue.popleft() + visited.add((tx, ty)) + for dtx, dty in directions: + ntx, nty = tx + dtx, ty + dty + + # 범위 검증 + if 0 <= ntx < R and 0 <= nty < C: + if (not (ntx, nty) in visited) and iceberg[ntx][nty]: + s_queue.append((ntx, nty)) + count += 1 + + # 하나의 점으로부터 bfs 탐색을 했을 때 모든 점이 카운트 되지 않았다면 2개 이상의 cycle이 생긴 것으로 확인 + if iceberg_count != count: + return True + return False + + +def solution(R: int, C: int, iceberg: list, queue: deque): + iceberg_count = len(queue) + + pre_year: int = 0 + + directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) + + record_iceberg: list = copy.deepcopy(iceberg) + + while queue: + year, x, y = queue.popleft() + + if year > pre_year: + iceberg = copy.deepcopy(record_iceberg) + start_point = (x, y) + + # 2개 이상의 덩어리가 생겼는지 확인 + if check_cycle(R, C, start_point, iceberg_count, iceberg): + return year + 1 + + # 4방향으로 탐색하며 빙산 값 업데이트 + temp_count = 0 + for dx, dy in directions: + nx, ny = x + dx, y + dy + + # 범위 검증 + if 0 <= nx < R and 0 <= ny < C: + # 0이라면 + if iceberg[nx][ny] == 0: + # 낮아지는 빙하 갯수 카운트 + temp_count += 1 + + # 업데이트 된 빙산 높이 업데이트 + record_iceberg[x][y] = max(0, iceberg[x][y] - temp_count) + + # 작업 큐 업데이트 + if record_iceberg[x][y]: + queue.append(((year + 1), x, y)) + else: + iceberg_count -= 1 + + pre_year = year + + # print() + # print(queue) + # for tr in iceberg: + # print(*tr) + # print() + # for tf in record_iceberg: + # print(*tf) + # print() + + return 0 + + +def main(): + R, C = map(int, input().split()) + + queue: deque = deque() + + iceberg: list = list() + + # 빙산 데이터 입력 받기 + for r in range(R): + data = list(map(int, input().split())) + checksum = sum(data) + # 빙산의 높이 값이 존재한다면 + if checksum: + for c in range(len(data)): + # 작업 큐 업데이트 (year, row, col) + queue.append((0, r, c)) + iceberg.append(data) + + return solution(R, C, iceberg, queue) + + +print(main()) From ab302c5c4716babdd03c6512d94af940a6cc08ee Mon Sep 17 00:00:00 2001 From: Woo-Yeol Date: Thu, 17 Aug 2023 03:05:21 +0900 Subject: [PATCH 2/2] =?UTF-8?q?Create=20=EB=B9=99=EC=82=B0=20wooyeol.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- "BOJ/\353\271\231\354\202\260/wooyeol.py" | 166 +++++++++------------ "BOJ/\353\271\231\354\202\260/wooyeol2.py" | 110 ++++++++++++++ 2 files changed, 182 insertions(+), 94 deletions(-) create mode 100644 "BOJ/\353\271\231\354\202\260/wooyeol2.py" diff --git "a/BOJ/\353\271\231\354\202\260/wooyeol.py" "b/BOJ/\353\271\231\354\202\260/wooyeol.py" index 80f6b8a5..8e3e3e50 100644 --- "a/BOJ/\353\271\231\354\202\260/wooyeol.py" +++ "b/BOJ/\353\271\231\354\202\260/wooyeol.py" @@ -3,119 +3,97 @@ https://www.acmicpc.net/problem/2573 풀이시간 - 10:33 ~ 14:12 (풀이 실패) + 10:33 ~ 14:12 (풀이 실패) + 4시간 (풀이 성공) 접근법 - 무슨 알고리즘으로 풀이 할 수 있을까? bfs + 무슨 알고리즘으로 풀이 할 수 있을까? BFS - 시간 초과와 메모리 초과로 실패했습니다. + 시간 초과와 메모리 초과로 실패했습니다. -> 리뷰를 보며 다시 풀이를 진행하여 풀이해낼 수 있었습니다. + - 빙산 테이블을 만들면서 빙산의 위치를 덱에 기억시켜놓고 첫 요소를 기점으로 BFS로 진행합니다. + - BFS 연산을 거치며 해당 빙산 주변 바다의 갯수를 통해 빙산의 높이를 조절합니다. + - 하나의 빙산 덩어리는 첫 요소를 기점으로 BFS를 진행하였을 때 모든 요소를 탐색 할 수 있습니다. + - 혹시라도 빙산의 위치를 저장시킨 덱의 요소를 다 검사하였을 때 한 번 더 BFS 탐색을 한다면 두 개의 빙산 덩어리가 발생하였다는 것 이므로 현재 연도를 반환 + - 만약 BFS 연산이 일어나지 않았다면 0개의 덩어리라는 것이므로 0을 반환 """ + import sys -import copy from collections import deque input = sys.stdin.readline +R, C = map(int, input().split()) -def check_cycle(R: int, C: int, start_point: tuple, iceberg_count: int, iceberg: list): - directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) - count: int = 1 - visited = set() - s_queue = deque([start_point]) - - while s_queue: - tx, ty = s_queue.popleft() - visited.add((tx, ty)) - for dtx, dty in directions: - ntx, nty = tx + dtx, ty + dty +iceberg_queue: deque = deque() - # 범위 검증 - if 0 <= ntx < R and 0 <= nty < C: - if (not (ntx, nty) in visited) and iceberg[ntx][nty]: - s_queue.append((ntx, nty)) - count += 1 +iceberg: list = list() - # 하나의 점으로부터 bfs 탐색을 했을 때 모든 점이 카운트 되지 않았다면 2개 이상의 cycle이 생긴 것으로 확인 - if iceberg_count != count: - return True - return False +# 빙산 데이터 입력 받기 +for r in range(R): + data = list(map(int, input().split())) + checksum = sum(data) + # 빙산의 높이 값이 존재한다면 + if checksum > 0: + for c in range(C): + # 작업 큐 업데이트 (year, row, col) + if data[c] != 0: + iceberg_queue.append((0, r, c)) + iceberg.append(data) -def solution(R: int, C: int, iceberg: list, queue: deque): - iceberg_count = len(queue) - - pre_year: int = 0 +def bfs(x: int, y: int): + q: deque = deque([(x, y)]) + visited[x][y] = True directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) - record_iceberg: list = copy.deepcopy(iceberg) - - while queue: - year, x, y = queue.popleft() + while q: + x, y = q.popleft() - if year > pre_year: - iceberg = copy.deepcopy(record_iceberg) - start_point = (x, y) - - # 2개 이상의 덩어리가 생겼는지 확인 - if check_cycle(R, C, start_point, iceberg_count, iceberg): - return year + 1 - - # 4방향으로 탐색하며 빙산 값 업데이트 - temp_count = 0 + # 4방향으로 탐색 for dx, dy in directions: nx, ny = x + dx, y + dy - # 범위 검증 - if 0 <= nx < R and 0 <= ny < C: - # 0이라면 - if iceberg[nx][ny] == 0: - # 낮아지는 빙하 갯수 카운트 - temp_count += 1 - - # 업데이트 된 빙산 높이 업데이트 - record_iceberg[x][y] = max(0, iceberg[x][y] - temp_count) - - # 작업 큐 업데이트 - if record_iceberg[x][y]: - queue.append(((year + 1), x, y)) - else: - iceberg_count -= 1 - - pre_year = year - - # print() - # print(queue) - # for tr in iceberg: - # print(*tr) - # print() - # for tf in record_iceberg: - # print(*tf) - # print() - - return 0 - - -def main(): - R, C = map(int, input().split()) - - queue: deque = deque() - - iceberg: list = list() - - # 빙산 데이터 입력 받기 - for r in range(R): - data = list(map(int, input().split())) - checksum = sum(data) - # 빙산의 높이 값이 존재한다면 - if checksum: - for c in range(len(data)): - # 작업 큐 업데이트 (year, row, col) - queue.append((0, r, c)) - iceberg.append(data) - - return solution(R, C, iceberg, queue) - - -print(main()) + # 방문 빙산인지 확인 + if (0 <= nx < R) and (0 <= ny < C) and not visited[nx][ny]: + # 주변에 바다가 있는지 확인하고 해당 칸이 바다인지도 확인 + if iceberg[nx][ny] == 0 and iceberg[x][y] != 0: + iceberg[x][y] -= 1 + + # 주변에 바다가 아닌 빙산이 있다면 다음 탐색을 위해 큐에 삽입 + if iceberg[nx][ny] != 0: + visited[nx][ny] = True + q.append((nx, ny)) + + # 4방향으로 바다를 검사했음에도 빙산이 녹지 않았다면 빙산 덱에 추가 + if iceberg[x][y] != 0: + iceberg_queue.append((current_year + 1, x, y)) + + return 1 + + +current_year = 0 +while True: + cnt = 0 + visited = [[False] * C for _ in range(R)] + + # print(f"\niceberg queue : {iceberg_queue}") + # print(f"current_year : {current_year}\n") + # for row in iceberg: + # print(*row) + + while iceberg_queue and iceberg_queue[0][0] == current_year: + y, r, c = iceberg_queue.popleft() + if iceberg[r][c] and not visited[r][c]: + cnt += bfs(r, c) + + # 빙산 덩어리 갯수가 2개 이상이 된다면 종료 + if cnt > 1: + print(current_year) + break + # 빙산 덩어리가 0개가 된다면 종료 + elif cnt == 0: + print(0) + break + # 빙산 덩어리가 1개라면 다시 다음해로 이동 + current_year += 1 diff --git "a/BOJ/\353\271\231\354\202\260/wooyeol2.py" "b/BOJ/\353\271\231\354\202\260/wooyeol2.py" new file mode 100644 index 00000000..b7523412 --- /dev/null +++ "b/BOJ/\353\271\231\354\202\260/wooyeol2.py" @@ -0,0 +1,110 @@ +# 메모리 초과로 인하여 실패나는 코드 + +import sys +from collections import deque + +input = sys.stdin.readline + + +def check_cycle(R: int, C: int, start_point: tuple, iceberg_count: int, iceberg: list): + directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) + count: int = 1 + visited = [[False] * C for _ in range(R)] + s_queue = deque([start_point]) + + while s_queue: + tx, ty = s_queue.popleft() + visited[tx][ty] = True + for dtx, dty in directions: + ntx, nty = tx + dtx, ty + dty + + # 범위 검증 + if 0 <= ntx < R and 0 <= nty < C: + if not visited[ntx][nty] and iceberg[ntx][nty]: + s_queue.append((ntx, nty)) + count += 1 + + # 하나의 점으로부터 bfs 탐색을 했을 때 모든 점이 카운트 되지 않았다면 2개 이상의 cycle이 생긴 것으로 확인 + if iceberg_count != count: + return True + return False + + +def solution(R: int, C: int, iceberg: list, queue: deque): + iceberg_count = len(queue) + + pre_year: int = 0 + + directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) + + record_iceberg: list = [item[:] for item in iceberg] + + while queue: + year, x, y = queue.popleft() + + if year > pre_year: + iceberg = [item[:] for item in record_iceberg] + start_point = (x, y) + + # 2개 이상의 덩어리가 생겼는지 확인 + if check_cycle(R, C, start_point, iceberg_count, iceberg): + return year + 1 + + # 4방향으로 탐색하며 빙산 값 업데이트 + temp_count = 0 + for dx, dy in directions: + nx, ny = x + dx, y + dy + + # 범위 검증 + if 0 <= nx < R and 0 <= ny < C: + # 0이라면 + if iceberg[nx][ny] == 0: + # 낮아지는 빙하 갯수 카운트 + temp_count += 1 + + # 업데이트 된 빙산 높이 업데이트 + record_iceberg[x][y] = max(0, iceberg[x][y] - temp_count) + + # 작업 큐 업데이트 + if record_iceberg[x][y]: + queue.append(((year + 1), x, y)) + else: + iceberg_count -= 1 + + pre_year = year + + # print() + # print(queue) + # for tr in iceberg: + # print(*tr) + # print() + # for tf in record_iceberg: + # print(*tf) + # print() + + return 0 + + +def main(): + R, C = map(int, input().split()) + + queue: deque = deque() + + iceberg: list = list() + + # 빙산 데이터 입력 받기 + for r in range(R): + data = list(map(int, input().split())) + checksum = sum(data) + # 빙산의 높이 값이 존재한다면 + if checksum > 0: + for c in range(C): + # 작업 큐 업데이트 (year, row, col) + if data[c] != 0: + queue.append((0, r, c)) + iceberg.append(data) + + return solution(R, C, iceberg, queue) + + +print(main())