This repository was archived by the owner on Mar 18, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
[2023-08-16] wooyeol #112 #127
Merged
Merged
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
""" | ||
빙산 | ||
https://www.acmicpc.net/problem/2573 | ||
|
||
풀이시간 | ||
10:33 ~ 14:12 (풀이 실패) + 4시간 (풀이 성공) | ||
|
||
접근법 | ||
무슨 알고리즘으로 풀이 할 수 있을까? BFS | ||
|
||
시간 초과와 메모리 초과로 실패했습니다. -> 리뷰를 보며 다시 풀이를 진행하여 풀이해낼 수 있었습니다. | ||
|
||
- 빙산 테이블을 만들면서 빙산의 위치를 덱에 기억시켜놓고 첫 요소를 기점으로 BFS로 진행합니다. | ||
- BFS 연산을 거치며 해당 빙산 주변 바다의 갯수를 통해 빙산의 높이를 조절합니다. | ||
- 하나의 빙산 덩어리는 첫 요소를 기점으로 BFS를 진행하였을 때 모든 요소를 탐색 할 수 있습니다. | ||
- 혹시라도 빙산의 위치를 저장시킨 덱의 요소를 다 검사하였을 때 한 번 더 BFS 탐색을 한다면 두 개의 빙산 덩어리가 발생하였다는 것 이므로 현재 연도를 반환 | ||
- 만약 BFS 연산이 일어나지 않았다면 0개의 덩어리라는 것이므로 0을 반환 | ||
""" | ||
|
||
import sys | ||
from collections import deque | ||
|
||
input = sys.stdin.readline | ||
|
||
R, C = map(int, input().split()) | ||
|
||
iceberg_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: | ||
iceberg_queue.append((0, r, c)) | ||
iceberg.append(data) | ||
|
||
|
||
def bfs(x: int, y: int): | ||
q: deque = deque([(x, y)]) | ||
visited[x][y] = True | ||
|
||
directions = ((1, 0), (-1, 0), (0, 1), (0, -1)) | ||
|
||
while q: | ||
x, y = q.popleft() | ||
|
||
# 4방향으로 탐색 | ||
for dx, dy in directions: | ||
nx, ny = x + dx, y + dy | ||
|
||
# 방문 빙산인지 확인 | ||
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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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()) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
iceberg_queue라는 작업 큐를 두신 게 굉장히 좋은 것 같아요! 저는 set 자료형으로 매번 copy를 했었는데 copy해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!