Processing math: 100%
본문 바로가기
프로그래밍/Python

[백준] 14503번 / 로봇청소기 / Python(파이썬)

by 나는 라미 2023. 10. 25.
728x90
반응형

14503번: 로봇 청소기 (acmicpc.net)

[14503번: 로봇 청소기

첫째 줄에 방의 크기 NM이 입력된다. (3N,M50)  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 (r,c)와 처음에 로봇 청소기가 바라보는 방향 d가 입력된다. d0인 경우 북쪽

www.acmicpc.net](https://www.acmicpc.net/problem/14503)

문제

로봇 청소기와 방의 상태가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.

로봇 청소기가 있는 방은 N×M 크기의 직사각형으로 나타낼 수 있으며, 1×1 크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북 중 하나이다. 방의 각 칸은 좌표 (r,c)로 나타낼 수 있고, 가장 북쪽 줄의 가장 서쪽 칸의 좌표가 (0,0), 가장 남쪽 줄의 가장 동쪽 칸의 좌표가 (N1,M1)이다. 즉, 좌표 (r,c)는 북쪽에서 (r+1)번째에 있는 줄의 서쪽에서 (c+1)번째 칸을 가리킨다. 처음에 빈 칸은 전부 청소되지 않은 상태이다. 로봇 청소기는 다음과 같이 작동한다.

1. 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
2. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,

    1) 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.

    2) 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
3. 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,

    1) 반시계 방향으로 90 회전한다.
    2) 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.

    3) 1번으로 돌아간다.

입력

첫째 줄에 방의 크기 NM이 입력된다.
(3N,M50)  둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 (r,c)와 처음에 로봇 청소기가 바라보는 방향 d가 입력된다. d0인 경우 북쪽, 1인 경우 동쪽, 2인 경우 남쪽, 3인 경우 서쪽을 바라보고 있는 것이다.

셋째 줄부터 N개의 줄에 각 장소의 상태를 나타내는 N×M개의 값이 한 줄에 M개씩 입력된다. i번째 줄의 j번째 값은 칸 (i,j)의 상태를 나타내며, 이 값이 0인 경우 (i,j)가 청소되지 않은 빈 칸이고, 1인 경우 (i,j)에 벽이 있는 것이다. 방의 가장 북쪽, 가장 남쪽, 가장 서쪽, 가장 동쪽 줄 중 하나 이상에 위치한 모든 칸에는 벽이 있다. 로봇 청소기가 있는 칸은 항상 빈 칸이다.

출력

로봇 청소기가 작동을 시작한 후 작동을 멈출 때까지 청소하는 칸의 개수를 출력한다.

풀이

이 문제는 4방향으로 이동하면서 칸을 조사하는 문제이기 때문에 dx, dy를 리스트로 설정하여 문제를 푸는 것이 효과적이다.

문제에서 주어진 대로 차례차례 구현하면 어려울 것은 없다.

 

1. 주변 4칸이 청소가 된 경우  ->  | 후진

                                                     | 후진 불가능하면 작동 멈춤

 

2. 주변 4칸 중 청소되지 않은 칸  -> 반시계 방향으로 90도 회전 후, 앞쪽 칸이 빈칸인 경우 전진 

 

- 방향 전환은 반시계 방향으로 움직이므로 4방향 주변 칸을 조사할 때 반시계 방향으로 조사한다.

- 후진 방향을 선택하기 위해 (d+2) % 4 식을 이용한다. 삼성 기출 문제에서는 방향을 전환하는 문제가 굉장히 많기 때문에 이런건 외워두는게 좋당

- 반시계 방향 회전은 (d+3) % 4를 이용한다. 간단한 문제지만 %4를 하는 이유는 4방향 안에서 자꾸 돌라고.. 

- 큐를 이용한 bfs로 문제를 풀면 간단하게 해결 할 수 있다.

   

코드

 

from collections import deque

# x, y가 좌표 내에 존재하는지 확인
def is_board(x, y):
    if 0 <= x < n and 0 <= y < m:
        return True
    return False

n, m = map(int, input().split())
r, c, d = map(int, input().split())

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

vaccum_map = [list(map(int, input().split())) for _ in range(n)]

def bfs(x, y, d):
    cnt = 0
    queue = deque()
    queue.append((x, y, d))
    # 현재 칸 청소
    vaccum_map[x][y] = 2
    cnt += 1
    while queue:
        x, y, d = queue.popleft()
        temp_d = d
        turn = 0
        for i in range(4):
            nd = (temp_d+3) % 4
            nx = x+dx[nd]
            ny = y+dy[nd]
            temp_d = nd
            if is_board(nx, ny):
                if vaccum_map[nx][ny] == 0:
                    queue.append([nx, ny, nd])
                    vaccum_map[nx][ny] = 2
                    cnt += 1
                    break
                else:
                    turn += 1
        # 주반 4칸에 빈 칸이 없는 경우 후진
        if turn == 4:
            bx = x + dx[(d+2) % 4]
            by = y + dy[(d+2) % 4]
            if vaccum_map[bx][by] == 1:
                return cnt
            queue.append((bx, by, d))
print(bfs(r, c, d))
728x90
반응형

댓글