This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all \u003cpre\u003e\u003ccode\u003e blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks"); } } catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); } })(); (function(){ try { var __m = "github.com"; var __re = new RegExp('^' + "github\\.com" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length \u003e 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content
This repository was archived by the owner on Mar 18, 2024. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions BOJ/빙산/wooyeol.py
Original file line numberDiff line numberDiff 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()

Copy link
Copy Markdown
Contributor

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해서 메모리가 계속 쌓이는 것보다 이 방식이 더 좋아보입니다 👍👍 고생하셨어요 우열님~!!!


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
110 changes: 110 additions & 0 deletions BOJ/빙산/wooyeol2.py
Original file line numberDiff line numberDiff 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())