백준 14503번: 로봇 청소기 [Python]

kimminjunnn·2026년 1월 30일

알고리즘

목록 보기
301/311

문제 출처 : https://www.acmicpc.net/problem/14503
난이도 : 골드 5


문제 파악

다음은 예제를 그림으로 표현한 것이다.

로봇의 이동방향 북,동,남,서 가 차례로 0,1,2,3 으로 주어지고

가운데 (1,1) 를 기준으로 벽이 둘러싸고 있다.

이때 로봇이 청소하는 개수는 제자리 한군데여서 1이다.

해답 및 풀이

import sys
input = sys.stdin.readline

# 0,0
# N-1, M-1
dx = [-1,0,1,0]
dy = [0,1,0,-1]

N, M = map(int,input().split()) # N, M 좌표
r, c, d = map(int,input().split()) # 현재 로봇의 좌표 r,c 바라보고 있는 방향 d (0=북쪽, 1=동쪽, 2=남쪽, 3=서쪽)

# 매트릭스 만들기
matrix = []
for _ in range(N):
    matrix.append(list(map(int,input().split())))
# [[1, 1, 1], [1, 0, 1], [1, 1, 1]]


cnt = 0

while True:
    # 현재 칸 청소
    if matrix[r][c] == 0:
        matrix[r][c] = 2 # 2는 청소했다는 의미
        cnt += 1

    # 4방향 중 청소 안된 칸 찾기
    found = False
    for _ in range(4):
        d = (d + 3) % 4 # d = d-1 인데 , 음수처리까지 안전하게 한 버전
        nr = r + dx[d]
        nc = c + dy[d]

        if matrix[nr][nc] == 0: # 반시계 방향 간 칸이 청소가 안됐다면,
            r, c = nr, nc # 이동
            found = True # 청소 안된 곳 마킹
            break
    
    # 4방향 청소가 다 됐다면 후진
    if not found:
        back = (d + 2) % 4
        br = r + dx[back]
        bc = c + dy[back]

        if matrix[br][bc] == 1: # 뒤로 이동할 좌표가 벽이라면 , 종료
            break
        r,c = br, bc # 벽이 아니라면 후진
    
print(cnt)

반시계 방향으로 이동하는 로직, 뒤로 이동하는 로직

이 문제를 풀기 위해서는 주어진 북,동,남,서 0,1,2,3 으로 장난질을 잘 쳐야한다.

북동남서이 시계방향으로 도는것이 0->1->2->3 +1씩 이니, 반시계방향은 -1씩 해주면 된다.

그러니 방향 d가 주어졌다면 d-1 을 해주면 반시계방향으로 가는데,
0에서 -1을 해주면 -1이 되니. 뺴는것말고 다른 연산을 해서 -1처리를 해주어야 하는데

그 스킬이 바로

d = (d+3) % 4

이렇게 d에 3,2,1,0을 대입해보면 2,1,0,3 이렇게 나옴을 볼 수 있다.

일단 이해하기보다 받아들이고 외우는 쪽으로 정했다.

활용해서 뒤로 이동하는 로직도 만들어보자.

뒤는 북동남서 0123 에서 북-> 남 가야하니 +2나 -2를 해주면 된다.

d = (d+2) % 4

을 해주면 우리가 원하는 0123안에서 후진을 표현할 수 있게 되겠다.

이를 다룰줄 알게 되면 다시 문제의 요구사항을 하나씩 차근차근 구현해보면 코드를 구현할 수 있을 것이다.


다시 풀어본 코드

import sys
input = sys.stdin.readline

# 입력
N, M = map(int,input().split())

r, c, d = map(int,input().split()) # 현재 위치, 보는 방향

matrix = []
for _ in range(N):
    matrix.append(list(map(int,input().split())))

# matrix = [[1, 1, 1], [1, 0, 1], [1, 1, 1]]


# 방향벡터, 북, 동, 남, 서 순으로 0, 1, 2, 3 (시계방향 +1)
dx = [-1,0,1,0]
dy = [0,1,0,-1]

cnt = 0

# 반시계로 이동하고자한다면 d = d-1 이지만, 음수도 처리해야하기에 d = (d+3) % 4
while True:
    # 0 청소 안됨, 1 벽, 2 청소 됨
    if matrix[r][c] == 0:
        matrix[r][c] = 2
        cnt += 1

    # 주변 4칸 반시계부터 탐색
    for _ in range(4):
        d = (d+3) % 4
        nr = r + dx[d]
        nc = c + dy[d]
            
        if matrix[nr][nc] == 0: # 새 장소가 청소가 안됐다?
            r, c = nr , nc # 새로 지정하고 탈출, 청소는 while문 첫번째에 할 것임
            break 
        
    # 여기까지 왔다는 것은 break 이 안됐다는 것, 즉 주변 4방향이 다 벽
    # 그렇다면 후진
    else: # for-else문. for문에 break가 안되었을 떄만 else문이 실행 됨.
        back = (d+2) % 4
        br = r + dx[back]
        bc = c + dy[back]
        # 후진할건데 만약 그곳이 벽이라면 로봇 종료.
        if matrix[br][bc] == 1:
            print(cnt) 
            exit(0)
        r, c = br,bc

for - else 문이 있다는 것을 처음 알았다.

for - else문은
for 문에 break가 없을때만 else가 실행됨.


다시 푼 코드

import sys
input = sys.stdin.readline

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

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

matrix = []

for _ in range(N):
    matrix.append(list(map(int,input().split())))

# 방향벡터, 북 0 동 1 남 2 서 3
dx = [-1,0,1,0]
dy = [0,1,0,-1]

cnt = 0 # 청소 횟수

while True:
    # 청소되지 않은 곳 0 , 벽 1 , 청소 된 곳 -1

    # 현재 칸이 아직 청소되지 않은 경우, 현재 칸을 '청소'한다.
    if matrix[r][c] == 0:
        matrix[r][c] = -1
        cnt += 1
    
    # 반시계 방향 90도 회전 후 앞으로 간 곳이 청소 되어있지 않은 곳이냐, 아니냐에 따른 분기
    for _ in range(4):
        d = (d+3) % 4

        nr = r + dx[d]
        nc = c + dy[d]

        # 반시계 90도 , 도착한 곳이 청소되지 않았다면, 좌표 이동 처리
        if matrix[nr][nc] == 0:
            r ,c = nr, nc
            break # 그리고 이동했으니 반시계 그만.

    else: 
        # for-else의 else문은 break 안됐을때 여기로 옴. 
        # 즉 반시계 다 돌았지만 청소 안된 곳이 없었다는 뜻.  그러면 후진 해야 함
        b = (d+2) % 4
        
        br = r + dx[b]
        bc = c + dy[b]

        # 만약 후진한 곳이 벽이라면, 로봇 종료.
        if matrix[br][bc] == 1:
            print(cnt) # 청소횟수 출력해주고 종료
            exit(0)
        
        # 위 if문에 안걸렸다는 것은 후진 한 곳이 벽이 아니라는 뜻
        # 그렇다면, 후진 한 좌표로 이동해주고 다시 while문 맨앞으로 보냄
        r, c = br, bc
profile
Frontend Engineers

0개의 댓글