여니의 취준 준비/코딩테스트 (Python)

[n14503] 로봇 청소기 in python

여니's 2021. 10. 22. 16:20


문제에 나와있는 순서대로만 구현하면

풀리는 문제!

 

빈칸 : 0, 벽 : 1, 청소한 칸 : 2로 구분하였다.

 

처음에는 청소한 구역도 1로 처리했는데

이렇게 하면 2번의 c,d조건을 판별할 수 없었다.

 

그리고

1번이랑 2번을 각각 독립적으로 움직이게끔

하는 과정이 살짝 버거웠다 ㅎ..

 

그리고 % 연산자를 활용해야 하는 부분을 잘 기억해야한다..

매번 헷갈리지만 ^0^

왼쪽 방향으로 돌릴 땐 (d+3)%4로 해주면 되는데,

d에 3을 더하는 이유에 대해 알아야

앞으로도 사용해먹을 수 있을 것 같아서

상세하게 풀어써보기!

 

방향은 0, 1, 2, 3 이렇게 있다.

3에서 왼쪽으로 움직이면 2가 되어야하는데 이때는 -1을 해주면 된다.

그러나 문제가 있다.

0에서 왼쪽으로 움직이면 방향은 3이 되어야한다.

그래서 -1을 해주면 위 경우에서 오류가 나게 된다.

 

(d+3)%4를 해주면

(0+3)%4 = 3이 된다!

 

만약 2만큼 회전시켜야 한다고 하면?

현재 방향과 반대되는 방향의 숫자 

즉, 0이 2가 되게 하는 방법은 간단하다.

 

(d+2)%4를 해주면 된다.

 

즉, (d+(n-움직이고자 하는 방향 수))%n을 해주면 된다 - !

 

 

 

실행시간은 112ms

 

다른 사람들 코드 보면서 

배워야겠다 :)  

# 북(0),동(1),남(2),서(3) (오른쪽,왼쪽,아래,위)
from collections import deque
from copy import deepcopy

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

n, m = map(int, input().split())
r, c, d = map(int, input().split())
array = [list(map(int, input().split())) for _ in range(n)]
answer = 0

def second(cnt):
    global r, c, d
    for i in range(4):
        nd = (d + 3) % 4
        nr = r + dx[nd]
        nc = c + dy[nd]
        if 0 <= nr < n and 0 <= nc < m:
            # a. 왼쪽 방향에 아직 청소하지 않은 공간이 존재한다면, 그 방향으로 회전한 다음 한 칸을 전진하고 1번부터 진행한다.
            if array[nr][nc] == 0:  # 방문하지 않은 곳
                r = nr
                c = nc
                d = nd
                return cnt
            # b. 왼쪽 방향에 청소할 공간이 없다면, 그 방향으로 회전하고 2번으로 돌아간다.
            else:
                cnt += 1
                d -= 1
    return cnt

# 빈칸 : 0, 벽 : 1, 청소 : 2
while True:
    # 1. 현재 위치를 청소한다.
    if array[r][c] == 0:
        array[r][c] = 2
        answer += 1
    cnt = 0
    # 2. # 2. 현재 위치에서 현재 방향을 기준으로 왼쪽 방향부터 차례대로 인접한 칸을 탐색한다
    cnt = second(cnt)

    if cnt == 4:
        nd = (d + 2) % 4
        nr = r + dx[nd]
        nc = c + dy[nd]
        # d. 네 방향 모두 청소가 이미 되어있거나 벽이면서, 뒤쪽 방향이 벽이라 후진도 할 수 없는 경우에는 작동을 멈춘다.
        if array[nr][nc] == 1:  
            print(answer)
            break
        # c. 네 방향 모두 청소가 이미 되어있거나 벽인 경우에는, 바라보는 방향을 유지한 채로 한 칸 후진을 하고 2번으로 돌아간다.
        else:  # (뒷편이 벽이 아닐 경우)
            r = nr
            c = nc

다른 사람들 풀이를 보니까

훨씬 간단하게 했던데..

내 코드가 지저분해보이는 마법 

1초도 걸리지 않았따..

 

다른 코드 참고해서

고쳐본 코드!

실행시간 68ms이당..!

 

두번째 과정을 따로 함수로 빼줄 필요도 없었다.처음에 시작하기 전에 현재 위치를 청소해놓고while문을 시작한다.

 

check 변수를 통해사방이 다 막혀잇는지 아닌지 체크한다.i==3이면서 check의 값이 0이면? -> 4방향이 벽이거나 청소한 곳이라는 거!

 

만약 뒷쪽에 있는 값이 1일 경우에는벽으로 막혀있으니 지나갈 수 없다.반복문 종료

 

1이 아니면? 청소했던 곳이라는 얘기니까지나갈 수는 있다청소를 또 못할 뿐!

 

dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]

n, m = map(int, input().split())
r, c, d = map(int, input().split())
array = [list(map(int, input().split())) for _ in range(n)]
answer = 1
array[r][c] = 2

while True:
    for i in range(4):
        nd = (d + 3) % 4
        nr = r + dx[nd]
        nc = c + dy[nd]

        if array[nr][nc] == 0:
            array[nr][nc] = 2
            answer += 1
            r = nr
            c = nc
            d = nd
            check = 1
            break
        else:
            d-=1
            check = 0

    if i == 3 and check == 0:  # 4방향 다 갈 수 없는 상태인 경우
        nd = (d + 2) % 4
        nr = r + dx[nd]
        nc = c + dy[nd]
        if array[nr][nc] == 1:  # 벽
            break
        else:  # 후진
            r = nr
            c = nc

print(answer)