본문 바로가기
Algorithm/Python

백준 25307번 시루의 백화점 구경

by Shark_상어 2023. 1. 5.
728x90

1. 문제 설명

문제링크

시루는 부모님과 함께 백화점에 갔다. 부모님은 쇼핑할 것이 많기 때문에 여러 곳을 돌아다녀야 하고, 시루는 부모님과 함께 걸어다니는 것이 너무 힘들어서 의자에 앉아서 쉬려고 한다.

백화점은 세로 길이가 N, 가로 길이가 M인 격자 형태이고, 상하좌우로 인접한 칸으로 이동할 때마다 1 만큼의 체력을 소모한다. 시루는 현재 위치에서 출발해 백화점 곳곳에 있는 의자 중 하나를 찾아가서 앉으려고 한다. 시루는 백화점 밖으로 나가면 부모님께 혼나기 때문에 백화점 밖으로 나갈 수 없다.

백화점에는 건물을 지탱하기 위한 기둥과 옷을 전시하기 위한 마네킹이 있다. 시루는 기둥이 있는 칸으로 이동하지 못하고, 마네킹을 무서워하기 때문에 마네킹과 거리가 K 이하인 칸은 사용하지 않으려고 한다. 이때 두 칸 (rx,cx),(ry,cy)의 거리는 |rx−ry|+|cx−cy|이다. 단, 시루가 출발할 때는 부모님과 함께 있기 때문에, 출발 지점과 마네킹과의 거리가 K 이하가 되어도 출발할 수 있다.

시루는 다리가 너무 아프기 때문에 체력 소모를 최소화하면서 의자까지 찾아가려고 한다. 시루가 소모하는 체력의 최솟값을 구해보자.

 

  • 입력
    • 첫째 줄에 백화점의 세로 길이, 가로 길이, 마네킹과 떨어져야 하는 거리를 의미하는 정수 N,M,K가 공백으로 구분되어 주어진다. (1≤N,M≤2000, 0≤K≤4000)
    • 둘째 줄부터 N개의 줄에 각각 M개씩 위에서부터 차례로 백화점의 상태가 주어진다. 아무것도 없는 칸은 0, 기둥이 있는 칸은 1, 의자가 있는 칸은 2, 마네킹이 있는 칸은 3, 시루의 시작 위치는 4로 주어진다. 시루의 시작 위치는 정확히 한 번 주어지고, 해당 위치에 기둥, 의자, 마네킹이 존재하지 않는다.
  • 출력
    • 시루가 의자를 찾아갈 수 있다면 시루가 소모하는 체력의 최솟값을 출력한다.
    • 만약 의자를 찾아갈 수 없다면 -1을 출력한다.

2. 코드

import sys
from collections import deque

input = sys.stdin.readline

# 4 방향 탐색
dx = [0, 0, 1, -1]
dy = [1, -1, 0, 0]

def bfs(a, b ,c):
    queue = deque()
    queue.append((a, b, c))

    # 만약 마네킹이 움직인 다면!! 가정으로 시작
    while mannequin_position:
        # 마네킹의 위치 와 거리
        mx, my, dis = mannequin_position.popleft()
        visit[mx][my] = True
        for i in range(4):
            mn_x = mx + dx[i]
            mn_y = my + dy[i]

            # 만약 범위를 벗어나지 않고 방문하지 않았다면
            if 0 <= mn_x < n and 0 <= mn_y < m and not visit[mn_x][mn_y]:
                # 그리고 거리가 k 이하 이라면
                if dis <= k:
                    # 방문 처리를 해준다
                    visit[mn_x][mn_y] = True
                    # 그 값을 다시 마네킹 위치에 넣어 준다.
                    mannequin_position.append((mn_x, mn_y , dis + 1))
    while queue:
        x, y, cnt = queue.popleft()
        for i in range(4):
            nx = x + dx[i]
            ny = y + dy[i]

            # 만약 범위를 벗어 나지 않고 방문 하지 않았다면
            if 0 <= nx < n and 0 <= ny < m and not visit[nx][ny]:
                # 그곳이 만약 빈칸 이라면
                if not maps[nx][ny]:
                    # 방문 처리를 해준다.
                    visit[nx][ny] = True
                    # 큐에 넣고 체력 값 + 1
                    queue.append((nx, ny, cnt + 1))
                # 그곳이 만약 의자 라면
                elif maps[nx][ny] == 2:
                    # 현재 소모된 체력 값 + 1 로 리턴
                    return cnt + 1
    # 의자로 가지 못한다면 -1
    return -1

# 백화점의 세로, 가로, 마네킹와 떨어져야 하는 길이
n, m ,k = map(int, input().split())

# 백화점 map를 담을 리스트
maps = []

# 시루의 위치 표시를 위한 변수
s_x, s_y = 0, 0

# 방문 처리를 위한 리스트
visit = [[False] * m for _ in range(n)]

# 마네킹 위치를 받을 큐 선언
mannequin_position = deque()

# 백화점 맵 정보를 받는 반복문
for i in range(n):
    a = list(map(int, input().split()))
    for j in range(m):
        # 만약 시루 위치라면
        if a[j] == 4:
            # 위치 갱신
            s_x, s_y = i, j
        # 마네킹 이라면 큐에 값 추가
        elif a[j] == 3:
            mannequin_position.append((i, j, 1))
    maps.append(a)
# 시루의 위치와 현재 소모된 체력 값으로 bfs 시작
print(bfs(s_x, s_y, 0))

3. 회고

Q. 문제를 보고 든 생각

  • 일반 적인 BFS 문제 라고 생각이 들었다.
  • 일반 적인 BFS 문제 이지만 혹시 마네킹이 움직 일수 있다면 그 곳을 방문 처리 하면 되지 않을까?? 라는 생각을 하게되었다. 그렇게 코드를 작성  했었고 색다르게 접근했던 것같아 재밌게 풀었던 문제이다.

4. 아쉬운 점 혹은 고쳐야 할점

마네킹을 움직여서 방문 처리를 했더니 시간복잡도 효율이 안좋은 것 같아 마네킹이 움직이지 않고 문제를 풀수있는 방법을 고안해내야 겠다.

728x90

'Algorithm > Python' 카테고리의 다른 글

백준 14503번 로봇 청소기  (0) 2023.01.07
백준 4991번 로봇 청소기  (0) 2023.01.07
백준 13023번 ABCDE  (1) 2023.01.05
백준 11053번 가장 긴 증가하는 부분 수열  (0) 2023.01.05
백준 17425번 약수의 합  (0) 2023.01.05