Skip to content
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
95 changes: 95 additions & 0 deletions YoonYn9915/Graph/2025-05-19-[백준]-#7576-토마토.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
'''
요구조건

1. 토마토는 격자 모양 상자의 칸에 하나씩 넣어서 창고에 보관한다.
2. 보관 후 하루가 지나면, 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익게 된다.(인접한 곳은 왼쪽, 오른쪽, 앞, 뒤를 의미한다)
3. 철수는 창고에 보관된 토마토들이 며칠이 지나면 다 익게 되는지, 그 최소 일수를 알고 싶어 한다. 모든 토마토가 익을 수 없다면 -1을 출력한다.

1. 아이디어
- 그래프를 탐색하여 최소 일수를 알아야 하므로 BFS
- 각 토마토가 익는 일수는 인접한 토마토가 익은 일수 + 1이므로 visited 배열을 사용해 토마토가 익는 일 저장

2. 시간복잡도
- 2 ≤ M,N ≤ 1,000
- BFS의 시간복잡도는 O(V+E) V는 최대 1,000,000, E는 최대 4,000,000. 1초 안에 가능

3. 구현
1. 입력받기
2. 초기 모든 토마토가 1이거나 -1인지 확인하기
3. bfs로 토마토 익히기 시뮬레이션
4. 모두 1이 아닌데 bfs가 끝나면 -1 반환, 모두 1이면 visited 배열 중 가장 큰 값(최소 일수) 출력.
'''
Comment on lines +1 to +21
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

매번 이렇게 요구조건과 아이디어, 시간복잡도를 적고 코드 풀이에 시작하시는 것 같은데 정말 배울 점인 것 같아요! 저는 알면서도 이게 잘 안 되더라구요..

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

원래 안했었는데 복잡한 문제는 풀다가 뭐했는지 까먹더라구요


import sys
from collections import deque

inp = sys.stdin.readline

M, N = map(int, inp().split())

arr = []
visited = [[-1] * M for _ in range(N)]

for _ in range(N):
arr.append(list(map(int, inp().split())))


def find_tomato(arr, visited):
tomatoes = []
for i in range(N):
for j in range(M):
if arr[i][j] == 1:
tomatoes.append((i, j))
visited[i][j] = 0
return tomatoes


def bfs(arr, visited):
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]

# 초기 설정
queue = deque(find_tomato(arr, visited))

# BFS
while queue:
x, y = queue.popleft()
for i in range(4):
new_x = x + dx[i]
new_y = y + dy[i]

# 상자 안이고, 0이고, 아직 방문하지 않았다면
if 0 <= new_x < N and 0 <= new_y < M and arr[new_x][new_y] == 0 and visited[new_x][new_y] == -1:
# 1로 바꾸고 방문처리하고 queue에 넣는다
arr[new_x][new_y] = 1
visited[new_x][new_y] = visited[x][y] + 1
queue.append((new_x, new_y))

def check_tomatoes(arr):
for i in range(N):
for j in range(M):
if arr[i][j] not in [-1, 1]:
return True
return False

# BFS가 끝난 후에 모두 1이 아니면 -1 반환, 모두 1이면 visited 중 가장 큰 값 찾기
if check_tomatoes(arr):
print(-1)
else:
print(max(map(max, visited)))

flag = False

# 초기에 모든 토마토가 1이거나 -1인지 확인하기
for i in range(N):
for j in range(M):
if arr[i][j] == 0:
flag = True
break

if flag:
bfs(arr, visited)
else:
print(0)


105 changes: 105 additions & 0 deletions YoonYn9915/Graph/2025-05-24-[백준]-#7569-토마토.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
'''
요구조건
1. 익은 토마토들의 인접한 곳에 있는 익지 않은 토마토들은 익은 토마토의 영향을 받아 익게 된다.
하나의 토마토에 인접한 곳은 위, 아래, 왼쪽, 오른쪽, 앞, 뒤 여섯 방향에 있는 토마토를 의미한다.


2. 토마토가 모두 익을 때까지 최소 며칠이 걸리는지를 계산해서 출력해야 한다.
만약, 저장될 때부터 모든 토마토가 익어있는 상태이면 0을 출력해야 하고,
토마토가 모두 익지는 못하는 상황이면 -1을 출력해야 한다.

1. 아이디어
- 익은 토마토의 인접한 곳으로 그래프 탐색을 해야 하므로 bfs 사용.
- 모든 토마토가 최소 몇 일에 익었는지 알기 위해서 토마토가 익은 일수를 저장해야 하므로 visited 배열에 저장.

2. 시간복잡도
- BFS의 시간복잡도는 O(V+E) V는 최대 1,000,000, E는 최대 6,000,000. 1초 안에 가능

3. 구현
3-1. 입력받기
3-2. 초기 모든 토마토가 1 혹은 -1인지 확인.
3-3. bfs 실행
3-4. 모두 1이 아닌데 bfs가 끝나면 -1 반환, 모두 1이면 visited 배열 중 가장 큰 값(최소 일수) 출력.

'''

from collections import deque
import sys

inp = sys.stdin.readline

# 가로, 세로, 높이
N, M, H = map(int, inp().strip().split())

arr = []
visited = [[[-1] * N for _ in range(M)] for _ in range(H)]

# 입력받기
for _ in range(H):
temp = []
for _ in range(M):
temp.append(list(map(int, inp().strip().split())))
arr.append(temp)

flag = False
# 초기 익은 토마토들을 저장하는 배열
tomatoes = []

# 초기 모든 토마토가 1 혹은 -1인지 확인.
for i in range(H):
for j in range(M):
for k in range(N):
if arr[i][j][k] == 0:
flag = True
break
if flag:
break
if flag:
break
Comment on lines +48 to +58
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이번에는 초기에 미리 1 혹은 -1인 코드를 체크하는군요! 만약 미리 체크하게 되면 바로 정답 출력하고 종료해도 좋을 것 같아요!


# 초기 1인 토마토 저장
for i in range(H):
for j in range(M):
for k in range(N):
if arr[i][j][k] == 1:
tomatoes.append((i, j, k))
visited[i][j][k] = 0


def bfs(arr, visited, tomatoes):
# 먼저 익은 토마토들로 큐 초기화
queue = deque(tomatoes)

# 상 하 좌 우 위 아래
dx = [-1, 1, 0, 0, 0, 0]
dy = [0, 0, -1, 1, 0, 0]
dz = [0, 0, 0, 0, -1, 1]

# bfs 탐색
while queue:
(z, y, x) = queue.popleft()
for idx in range(6):
# 인접 칸으로 이동
new_z = z + dz[idx]
new_y = y + dy[idx]
new_x = x + dx[idx]

# 조건 확인(1. 인접칸의 인덱스가 범위 안인지, 2. 인접칸이 안익은 토마토인지, 3. 인접칸이 방문한적 없는지)
if (0 <= new_x < N and 0 <= new_y < M and 0 <= new_z < H) and (arr[new_z][new_y][new_x] == 0) and \
(visited[new_z][new_y][new_x] == -1):
# 방문처리
queue.append((new_z, new_y, new_x))
arr[new_z][new_y][new_x] = 1
visited[new_z][new_y][new_x] = visited[z][y][x] + 1

# bfs가 끝났을 때, arr 배열에 0이 하나라도 있으면 -1 출력, 그렇지 않으면 visited 배열 요소 중 가장 큰 값 출력
if any(item == 0 for depth in arr for row in depth for item in row):
print(-1)
else:
print(max(item for depth in visited for row in depth for item in row))


if flag:
bfs(arr, visited, tomatoes)
else:
print(0)
70 changes: 70 additions & 0 deletions YoonYn9915/implementation/2025-05-24-[백준]-#16509-장군.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
'''
1. 아이디어
- 상이 왕에게 도달할 수 있는 최소 횟수를 구하기 위해 장기판을 그래프로 놓고 상이 갈 수 있는 위치를 bfs로 탐색한다.

2. 시간복잡도
- BFS 시간복잡도 O(V + E), V는 10 * 9 , E는 최대 4 * 10 * 9.

3. 구현
3.1 입력받기
3.2 상의 초기 위치에서부터 8가지 방향으로 나아가며 bfs 실행.
3.3 이동 경로에 왕이 있으면 이동 불가
3.4 bfs가 끝나기 전에 왕의 위치에 도달하면 이동횟수 출력, 도달하지 못하면 -1 출력
'''

from collections import deque

# 입력 받기
R1, C1 = map(int, input().split()) # 상의 시작 위치
R2, C2 = map(int, input().split()) # 왕의 위치

# 방문 여부를 -1로 초기화 (10행 x 9열)
visited = [[-1] * 9 for _ in range(10)]
visited[R1][C1] = 0 # 시작 위치는 0으로 표시

# 상의 8가지 이동 방향 및 그에 따른 경유 좌표 정의
# 각각: 경유1, 경유2, 최종 목적지 (총 3단계 이동)
paths = [
[(-1, 0), (-2, -1), (-3, -2)],
[(-1, 0), (-2, 1), (-3, 2)],
[(1, 0), (2, -1), (3, -2)],
[(1, 0), (2, 1), (3, 2)],
[(0, -1), (-1, -2), (-2, -3)],
[(0, -1), (1, -2), (2, -3)],
[(0, 1), (-1, 2), (-2, 3)],
[(0, 1), (1, 2), (2, 3)],
]

# 이동 경로에 왕이 있는지 확인
def check(x, y, i):
for dx, dy in paths[i][:2]: # 경유지 두 곳만 확인
mx, my = x + dx, y + dy
if mx == R2 and my == C2:
return False
return True

# BFS로 최소 이동 횟수 찾기
def bfs():
queue = deque([(R1, C1)])

while queue:
x, y = queue.popleft()

# 왕의 위치에 도달한 경우
if x == R2 and y == C2:
print(visited[x][y])
return

for i in range(8):
nx = x + paths[i][2][0]
ny = y + paths[i][2][1]

# 범위 안이고, 방문하지 않았으며, 경로에 왕이 없다면
if 0 <= nx < 10 and 0 <= ny < 9 and visited[nx][ny] == -1 and check(x, y, i):
visited[nx][ny] = visited[x][y] + 1
queue.append((nx, ny))

# 도달할 수 없는 경우
print(-1)

bfs()