본문 바로가기

알고리즘/백준

백준 14503 - 로봇 청소기 (Python)

https://www.acmicpc.net/problem/14503

 

문제


 

 

풀이


# 방의 크기
n,m = map(int,input().split())
# 로봇 청소기가 있는 방의 좌표(r,c)와 로봇청소기가 바라보는 방향(d)
r,c,d = map(int,input().split())

# d = 0 (북), 1(동), 2(남), 3(서)

room = []

for i in range(n):
    room_num = list(map(int,input().split()))
    room.append(room_num)

# 4방향을 체크한다. (청소할 구역이 있는지 없는지)
def check4can(r,c,room):
    cnt = 0

    # 먼저 r,c가 최상단 (0,0), 최하단 (n-1,m-1)에 있을 때를 배제
    if r == 0 and c == 0:
        if room[r+1][c] == 0 or room[r][c+1] == 0:
            cnt += 1
    elif r == n-1 and c == m-1:
        if room[r-1][c] == 0 or room[r][c-1] == 0:
            cnt += 1
    # 이후 r,c가 단독으로 최상단 혹은 최하단에 존재할 경우를 나눠줌
    else:
        if r == 0:
            if room[r+1][c] == 0 or room[r][c-1] == 0 or room[r][c+1] == 0:
                cnt += 1
        elif c == 0:
            if room[r+1][c] == 0 or room[r-1][c] == 0 or room[r][c+1] == 0:
                cnt += 1
        elif r == n-1:
            if room[r-1][c] == 0 or room[r][c-1] == 0 or room[r][c+1] == 0:
                cnt += 1
        elif c == m-1:
            if room[r+1][c] == 0 or room[r-1][c] == 0 or room[r][c-1] == 0:
                cnt += 1
        else:
            if room[r-1][c] == 0 or room[r][c-1] == 0 or room[r+1][c] == 0 or room[r][c+1] == 0:
                cnt += 1

    # 만약 청소할 구역이 남았다면 False, 없다면 True를 보낸다.
    if cnt == 0:
        return True
    else:
        return False

answer = 0

while True:
    # 문제에서 1번에 해당 청소되지 않았으면 현재 칸을 청소, 그리고 2로 바꿔준다. (2는 청소를 했다는 표시)
    # 청소를 했다면 후진을 할 수 있지만 3번에서 이동이 안된다.
    if room[r][c] == 0:
        answer += 1
        room[r][c] = 2

    # 만약 4방향 모두 청소할 곳이 없다면
    if check4can(r,c,room):
        # 만약 방향이 북쪽이면 후진하면 남쪽 그러면 r == n-1이 아니라면 후진 가능 r을 +1 해준다.
        if d == 0:
            if r != n-1 and room[r+1][c] != 1:
                r = r+1
            else:
                break
        # 만약 방향이 동쪽이면 후진하면 서쪽 그러면 c == 0이 아니라면 후진 가능 c을 -1 해준다.
        elif d == 1:
            if c != 0 and room[r][c-1] != 1:
                c = c-1
            else:
                break
        # 만약 방향이 남쪽이면 후진하면 북쪽 그러면 r == 0이 아니라면 후진 가능 r을 -1 해준다.
        elif d == 2:
            if r != 0 and room[r-1][c] != 1:
                r = r-1
            else:
                break
        # 만약 방향이 서쪽이면 후진하면 동쪽 그러면 c == m-1이 아니라면 후진 가능 c를 +1 해준다.
        else:
            if c != m-1 and room[r][c+1] != 1:
                c = c+1
            else:
                break
    # 만약 4방향 중 청소할 곳이 있다면
    else:
        # 4방향 중 청소할 곳을 찾는다.
        # 무조건 현재 방향에서 90도로 돌려야하므로 90도를 반복해서 돌리면서 0인 곳을 찾음
        while True:
            # 현재 방향에서 90도를 돌려주고
            if d == 0:
                d = 3
                # 만약 칸의 끝지점이 아니고 1(벽) 2(이미 청소한 구역)이 아니라면 전진한다.
                if c != 0 and room[r][c-1] == 0:
                    c = c - 1
                    break
            elif d == 1:
                d = 0

                if r != 0 and room[r-1][c] == 0:
                    r = r - 1
                    break
            elif d == 2:
                d = 1

                if c != m and room[r][c + 1] == 0:
                    c = c + 1
                    break
            else:
                d = 2

                if r != n and room[r + 1][c] == 0:
                    r = r + 1
                    break


# 정답을 출력
print(answer)

 

구현으로 풀이하였다. 

 

 

느낀점


문제 자체 이해가 조금 힘들어서 헷갈린 부분이 좀 있었다.

 

먼저 1은 청소가 끝난 구역이 아니라 "벽"이다.

 

처음에 벽을 가장자리 부분으로 착각했는데 숫자 1자체가 벽이였다.

 

그리고 후진은 청소를 진행했던 (방문한) 구역이여도 후진이 가능하지만 전진(청소할 구역이 남아있는 경우)은 이미 청소한 구역일 경우 전진할 수 없다. (벽은 당연히 안된다) 즉, 벽이 아닌 청소를 해야하는 구역으로만 전진이 가능하다.

 

마지막에 저 부분이 헷갈렸다. 그래서 후진은 1만 아니면 후진을 하지만 전진은 0이여야 전진할 수 있음