[백준][Python] 14503. 로봇 청소기
Gold Ⅴ 🔗14503. 로봇 청소기
📝문제 요약
문제 설명
로봇 청소기와 방의 상태가 주어졌을 때, 청소하는 영역의 개수를 구하는 프로그램을 작성하시오.
로봇 청소기가 있는 방은$N \times M$ 크기의 직사각형으로 나타낼 수 있으며, $1 \times 1$ 크기의 정사각형 칸으로 나누어져 있다. 각각의 칸은 벽 또는 빈 칸이다. 청소기는 바라보는 방향이 있으며, 이 방향은 동, 서, 남, 북 중 하나이다. 방의 각 칸은 좌표 $(r, c)$로 나타낼 수 있고, 가장 북쪽 줄의 가장 서쪽 칸의 좌표가 $(0, 0)$, 가장 남쪽 줄의 가장 동쪽 칸의 좌표가 $(N-1, M-1)$이다. 즉, 좌표 $(r, c)$는 북쪽에서 $(r+1)$번째에 있는 줄의 서쪽에서 $(c+1)$번째 칸을 가리킨다. 처음에 빈 칸은 전부 청소되지 않은 상태이다.
로봇 청소기는 다음과 같이 작동한다.
- 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 청소한다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 없는 경우,
- 바라보는 방향을 유지한 채로 한 칸 후진할 수 있다면 한 칸 후진하고 1번으로 돌아간다.
- 바라보는 방향의 뒤쪽 칸이 벽이라 후진할 수 없다면 작동을 멈춘다.
- 현재 칸의 주변 4칸 중 청소되지 않은 빈 칸이 있는 경우,
- 반시계 방향으로 $90^\circ$ 회전한다.
- 바라보는 방향을 기준으로 앞쪽 칸이 청소되지 않은 빈 칸인 경우 한 칸 전진한다.
- 1번으로 돌아간다.
입력
첫째 줄에 방의 크기 $N$과 $M$이 입력된다. $(3 \le N, M \le 50)$ 둘째 줄에 처음에 로봇 청소기가 있는 칸의 좌표 $(r, c)$와 처음에 로봇 청소기가 바라보는 방향 $d$가 입력된다. $d$가 $0$인 경우 북쪽, $1$인 경우 동쪽, $2$인 경우 남쪽, $3$인 경우 서쪽을 바라보고 있는 것이다.
셋째 줄부터 $N$개의 줄에 각 장소의 상태를 나타내는 $N \times M$개의 값이 한 줄에 $M$개씩 입력된다. $i$번째 줄의 $j$번째 값은 칸 $(i, j)$의 상태를 나타내며, 이 값이 $0$인 경우 $(i, j)$가 청소되지 않은 빈 칸이고, $1$인 경우 $(i, j)$에 벽이 있는 것이다. 방의 가장 북쪽, 가장 남쪽, 가장 서쪽, 가장 동쪽 줄 중 하나 이상에 위치한 모든 칸에는 벽이 있다. 로봇 청소기가 있는 칸은 항상 빈 칸이다.
출력
로봇 청소기가 작동을 시작한 후 작동을 멈출 때까지 청소하는 칸의 개수를 출력한다.
✏️문제 풀이
- 방의 크기
n
,m
을 입력 - 좌표
r
,c
와 로봇이 바라보는 방향d
를 입력 받음 n * m
의 방 상태를 입력받음- 4방향(북, 동, 남, 서)에 청소할 칸이 하나라도 있는지 확인
- 하나라도 있으면,
clean = False
로 바꾸고 더 이상 확인하지 않음 - 모두 청소되었거나 벽이라면
clean = True
- 하나라도 있으면,
- 청소할 곳이 있는 경우 (
clean == False
)- 왼쪽으로 회전
- 회전한 방향에 청소되지 않은 칸(0)이 있으면, 그 방향으로 한 칸 이동해서 다시 루프 반복
- 청소할 곳이 없는 경우 (
clean == True
)- 후진할 수 있는지 확인
- 후진 방향은 현재 방향의 반대
- 뒤쪽이 벽이 아니면 후진해서 다시 루프 시작
- 벽이면 더 이상 움직일 수 없으니 청소 종료
- 지금까지 청소한 칸 수 출력
코드와 함께 보는 풀이
# 방 크기 입력
n, m = map(int, input().split())
# 로봇의 초기 위치 (r, c)와 방향 d 입력
# d : 0=북, 1=동, 2=남, 3=서
r, c, d = map(int, input().split())
# 방의 상태 입력 (0=청소되지 않음, 1=벽)
robot = [list(map(int, input().split())) for _ in range(n)]
# 방향별 이동값 설정 (북, 동, 남, 서)
robot_x = [-1, 0, 1, 0]
robot_y = [0, 1, 0, -1]
# 청소한 칸 수
cnt = 0
# 현재 로봇 위치
x, y = r, c
while True:
# 현재 칸이 아직 청소되지 않은 경우
if robot[x][y] == 0:
# 청소 완료 표시 : 2
robot[x][y] = 2
# 청소한 칸 수 증가
cnt += 1
# 주변에 청소할 곳이 있는지 확인(True : 없음)
clean = True
# 현재 위치를 기준으로 4방향 탐색
for i in range(4):
nx = x + robot_x[i]
ny = y + robot_y[i]
# 범위 안이고, 청소되지 않은 칸이 있는 경우
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] == 0:
# 청소할 하나라도 있으면 더 확인할 필요 없음
clean = False
break
# 모든 방향이 청소되어 있거나 벽이라면 후진 시도
if clean:
# 현재 방향에서 뒤로 돌아감
back = (d + 2) % 4
nx = x + robot_x[back]
ny = y + robot_y[back]
# 뒤쪽 칸이 벽이 아니라면 후진
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] != 1:
x, y = nx, ny
# 뒤가 벽이면 작동 멈춤
else:
break
# 청소할 칸이 있으면
else:
# 반시계 방향으로 회전
d = (d + 3) % 4
nx = x + robot_x[d]
ny = y + robot_y[d]
# 회전한 방향에 청소할 수 있는 칸이 있다면 전진
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] == 0:
x, y = nx, ny
# 최종적으로 청소한 칸의 수 출력
print(cnt)
💯제출 코드
n, m = map(int, input().split())
r, c, d = map(int, input().split())
robot = [list(map(int, input().split())) for _ in range(n)]
robot_x = [-1, 0, 1, 0]
robot_y = [0, 1, 0, -1]
cnt = 0
x, y = r, c
while True:
if robot[x][y] == 0:
robot[x][y] = 2
cnt += 1
clean = True
for i in range(4):
nx = x + robot_x[i]
ny = y + robot_y[i]
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] == 0:
clean = False
break
if clean:
back = (d + 2) % 4
nx = x + robot_x[back]
ny = y + robot_y[back]
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] != 1:
x, y = nx, ny
else:
break
else:
d = (d + 3) % 4
nx = x + robot_x[d]
ny = y + robot_y[d]
if 0 <= nx < n and 0 <= ny < m and robot[nx][ny] == 0:
x, y = nx, ny
print(cnt)
댓글남기기