Skip to content

Conversation

@YoonYn9915
Copy link
Member

🌱WIL

이번 한 주의 소감을 작성해주세요!

  • 이번 주는 그래프 유형, 정확히는 BFS, 골드 난이도 3문제를 풀어보았다. 세 문제 다 방향성은 금방 잡혔는데, 잔실수가 많아서 좀 시간을 오래 썼다. 7569번 문제는 오랫만에 3차원 리스트를 썼는데, arr[x축][y축][z축]형태로 썼다가 디버깅 하느라 한참 헤맸다. 그래도 확실히 이제는 문제 유형을 파악하고 구현 방법을 생각해내는게 어렵지는 않았다.

🚀주간 목표 문제 수: 3개

푼 문제


백준 #7576. 토마토: 그래프 / 골드 5

정리한 링크: (바로가기)

🚩제출한 코드

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)

💡TIL

배운 점이 있다면 입력해주세요


백준 #7569. 토마토: 그래프 / 골드 5

정리한 링크: (바로가기)

🚩제출한 코드

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

# 초기 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)

💡TIL

배운 점이 있다면 입력해주세요


백준 #16509. 장군: 그래프 / 골드 5

정리한 링크: (바로가기)

🚩제출한 코드

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()

💡TIL

배운 점이 있다면 입력해주세요

Copy link
Collaborator

@Mingguriguri Mingguriguri left a comment

Choose a reason for hiding this comment

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

이번 한 주도 고생 많으셨습니다!

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.

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

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인 코드를 체크하는군요! 만약 미리 체크하게 되면 바로 정답 출력하고 종료해도 좋을 것 같아요!

@YoonYn9915 YoonYn9915 merged commit 0b119ee into main May 26, 2025
@github-actions
Copy link

🔥2025-05 챌린지 진행 상황

👉 그래프

  • YoonYn9915: 3개 ❌
  • Mingguriguri: 0개 ❌

👉 구현

  • YoonYn9915: 2개 ❌
  • Mingguriguri: 2개 ❌

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants