이번 문제는 생각보다 다른 문제들보다 길고 어려웠습니다. 열심히 짱구를 굴려가며 코딩해봤지만 계속 틀렸습니다.. 그래도 계속 보다 보니까 어느정도 이해가 돼서 꽤 잘 풀었던 것 같습니다.
문제 설명
1. 현재 위치에서 현재 방향을 기준으로 왼쪽방향부터 차례대로 갈 곳을 정한다.
2. 캐릭터의 바로 왼쪽 방향에 아직 가보지 않은 칸이 존재한다면, 왼쪽 방향으로 회전한 다음 왼쪽으로 한 칸을 전진한다. 왼쪽 방향에 가보지 않은 칸이 없다면, 왼쪽 방향으로 회전만 수행하고 1단계로 돌아간다.
3. 만약 네 방향이 모두 가본 칸이거나 바다로 되어 있는 칸인 경우에는, 바라보는 방향을 유지한 채로 한 칸 뒤로 가고 1단계로 돌아간다. 단, 이 때 뒤쪽 방향이 바다인 칸이라 뒤로 갈 수 없는 경우에는 움직임을 멈춘다.
입력 조건은 첫째줄에는 세로크기 N과 가로크기 M이 공백으로 주어지며, 둘째 줄에는 캐릭터가 있는 칸의 좌표와 바라보는 방향 d가 각각 공백으로 주어집니다. 방향 d는 0: 북쪽, 1: 동쪽, 2: 남쪽, 3: 서쪽이며, 셋째 줄부터는 맵의 정보가 주어집니다. 출력조건은 캐릭터가 방문한 칸의 수를 출력합니다.
문제 해결 아이디어
어떻게 해야할지 생각이 안나서, 그냥 조건이 주어진대로 주석을 달면서 구현해버렸습니다. 풀고나서 생각해보니, 구현 단원이었다는... 어쨌거나 조건대로 현재 바라보는 방향에서 왼쪽방향으로 회전시키고, 아직 가보지 않은 칸이면서 육지이면 이동 후에 방문처리를 했습니다. 육지가 아니면 회전을 했고, 4번 모두 회전했는데 갈 수 있는데가 없으면 뒤로 가기를 했습니다. 육지이면 위치를 업데이트하고 회전횟수를 리셋시켰고, 바다일 경우엔 탈출하도록 구현했습니다.
row, col = map(int, input().split())
curR, curC, d = map(int, input().split())
#북동남서
dr = [-1, 0, 1, 0]
dc = [0, 1, 0, -1]
array = []
for _ in range(row):
array.append(list(map(int, input().split())))
visited = [[False] * col for _ in range(row)]
visited[curR][curC] = True
cnt = 1
cntTurn = 0 # 현재 위치에서 몇 번 돌았는지 카운트
while True:
#왼쪽으로 회전
d -= 1
if d == -1:
d = 3
nr = curR + dr[d]
nc = curC + dc[d]
# 범위를 벗어나지 않고, 방문하지 않았으면서 육지이면
if nr >= 0 and nr < row and nc >= 0 and nc < col and not visited[nr][nc] and array[nr][nc] == 0:
#현재 위치 업데이트하고 방문처리, 방문했으니까 카운트, 자리 옮긴 후 현위치에서 회전은 0번
curR = nr
curC = nc
visited[curR][curC] = True
cnt += 1
cntTurn = 0
# 왼쪽이 방문한데 이거나 바다이면 회전하기
else:
cntTurn += 1
#현 위치에서 회전 횟수가 4회이면(4면이 바다이거나 방문한데면)
if cntTurn == 4:
#현재 바라보는 방향에서 뒤로 빼기
nr = curR - dr[d]
nc = curC - dc[d]
#뒤로 이동한 위치가 범위를 벗어나지 않으면서 육지이면
if nr >= 0 and nr < row and nc >= 0 and nc < col and array[nr][nc] == 0:
#위치 업데이트하고 회전횟수 0으로 초기화
curR = nr
curC = nc
cntTurn = 0
#뒤가 범위를 벗어나지는 않지만, 더 이상 바다밖에 없으면 탈출
elif nr >= 0 and nr < row and nc >= 0 and nc < col and array[nr][nc] == 1:
break
print(cnt)
책의 문제풀이 방법
# N, M을 공백을 기준으로 구분하여 입력받기
n, m = map(int, input().split())
# 방문한 위치를 저장하기 위한 맵을 생성하여 0으로 초기화
d = [[0] * m for _ in range(n)]
# 현재 캐릭터의 X 좌표, Y 좌표, 방향을 입력받기
x, y, direction = map(int, input().split())
d[x][y] = 1 # 현재 좌표 방문 처리
# 전체 맵 정보를 입력받기
array = []
for i in range(n):
array.append(list(map(int, input().split())))
# 북, 동, 남, 서 방향 정의
dx = [-1, 0, 1, 0]
dy = [0, 1, 0, -1]
# 왼쪽으로 회전
def turn_left():
global direction
direction -= 1
if direction == -1:
direction = 3
# 시뮬레이션 시작
count = 1
turn_time = 0
while True:
# 왼쪽으로 회전
turn_left()
nx = x + dx[direction]
ny = y + dy[direction]
# 회전한 이후 정면에 가보지 않은 칸이 존재하는 경우 이동
if d[nx][ny] == 0 and array[nx][ny] == 0:
d[nx][ny] = 1
x = nx
y = ny
count += 1
turn_time = 0
continue
# 회전한 이후 정면에 가보지 않은 칸이 없거나 바다인 경우
else:
turn_time += 1
# 네 방향 모두 갈 수 없는 경우
if turn_time == 4:
nx = x - dx[direction]
ny = y - dy[direction]
# 뒤로 갈 수 있다면 이동하기
if array[nx][ny] == 0:
x = nx
y = ny
# 뒤가 바다로 막혀있는 경우
else:
break
turn_time = 0
# 정답 출력
print(count)
아이디어가 같았다는건 착각이겠죠?
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
[이코테 - DFS/BFS] 미로탈출 (1) | 2022.10.11 |
---|---|
[이코테 - DFS/BFS] 음료수 얼려먹기 (0) | 2022.10.10 |
[이코테 - 구현] 왕실의 나이트 (0) | 2022.10.08 |
[이코테 - 구현] 시각 (1) | 2022.10.05 |
[이코테-구현] 상하좌우 (1) | 2022.10.04 |
댓글