

문제 출처 : 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