백준(BOJ) 시뮬레이션: 로봇 시뮬레이션(골드 5)
문제 출처: https://www.acmicpc.net/problem/2174
1. 알고리즘
문제 설명에서 요구하는 대로만 코드 작성하면 되는 문제
dictionary 자료형으로 로봇의 정보를 저장해두고, 명령에 따라 값(로봇의 위치, 방향)을 바꾸어 주도록 함.
- 로봇의 데이터를 입력받으면서, 순서대로 로봇 dictionary에 값(로봇의 행, 열, 방향)을 저장
- 명령의 횟수만큼 반복
- 입력받은 명령에 따라 해당하는 번호의 로봇을 dictionary에서 뽑아옴.
- 회전 명령이면
- 'L'인 경우, 반복 횟수만큼 방향에 값(1*반복횟수)을 더해주고, 4 나머지 연산
- 'R'인 경우, 반복 횟수만큼 방향에 값(3*반복횟수)을 더해주고, 4 나머지 연산
- 전진 명령이면('F')
- 로봇의 행, 열에 방향만큼 한 칸 전진
- 로봇이 땅 범위 내에 위치해 있는 지 확인.
- 땅 범위 밖으로 벗어난 경우, 'Robot X crashes into the wall'을 출력하고, 종료 flag를 True로 변경, 전진 명령 break
- 다른 로봇들 중 현재 이동한 칸에 위치한 로봇이 존재하는 지 확인.
- 동일한 위치에 로봇이 존재할 경우, 'Robot X crashes into robot Y'를 출력하고, 종료 flag를 True로 변경, dictionary 탐색 반복문 break
- 종료 플래그가 True 인경우, 전진 명령 반복 break
- 종료 플래그가 True인 경우, 명령 받기 break
- 종료 플래그가 False인 경우, 로봇 dictionary의 해당 번호 로봇 정보 입력(갱신)
- 종료 플래그가 False인 경우(정상 작동으로 모든 명령을 완료한 경우), 'OK' 출력
2. 유의 사항
- 값 입력받을 때,
- A가 가로(열 갯수), B가 세로(행 갯수)임. 또, 좌표 처리 시 행 좌표가 아래에서부터 1, 열 좌표가 1에서부터 시작함에 유의
- '1 1 E' / '1 L 5'등 int형과 str형 혼재 주의
- 회전 명령 수행 시, 회전도 반복해서 수행해야함
- 전진 명령 수행 시, num을 곱해서 한 번에 이동시키면 이동 중 다른 로봇에 충돌하는 경우를 알 수 없음
- 한 칸 전진할 때마다의 범위, 다른 로봇에 대한 확인을 해줘야함
3. 어려웠던 점, 해결 방법
- 좌표 처리할 때 행 좌표가 아래에서부터 1인 것 때문에 처리를 잘못해주어 오류가 있었음. (행 길이)-(입력받은 행 번호)로 수정하여 해결
- 회전 수행 시, 반복해서 수행해주지 않아 오류가 발생했었음.
- 전진 수행 시, 한 번에 이동시켜서 확인해주는 식으로 작성하여, 이동하는 중에 로봇과 충돌하는 경우를 알수 없어 틀렸었음. 한 칸씩 이동할 때마다 확인해주는 것으로 변경.
4. 소스코드
상세 코드 설명은 주석 참고
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
|
import sys
from collections import defaultdict
input_func = sys.stdin.readline
if __name__ == '__main__':
A, B = map(int, input_func().split())
N, M = map(int, input_func().split())
robots = defaultdict(tuple)
#문자로 입력받은 방향을 숫자로 변경시켜주기 위한 방향 맵핑 딕셔너리
directions = {'N': 0, 'W': 1, 'E': 3, 'S': 2}
for idx in range(N):
x, y, d = map(str, input_func().split())
#행 좌표(행 길이-입력행번호), 열 좌표(입력 열번호 - 1)
robots[idx + 1] = (B - int(y), int(x) - 1, directions[d])
dx = [-1, 0, 1, 0]
dy = [0, -1, 0, 1]
flag = False
#명령을 입력받아 수행
for idx in range(M):
id, cmd, num = map(str, input_func().split())
#문자열로 입력받았으니 숫자로 변경
id, num = int(id), int(num)
robot_x, robot_y, robot_d = robots.pop(id)
#명령 수행
if cmd == 'L':
#4번 회전하면 같은 방향
num %= 4
#방향은 4방향
robot_d = (robot_d + (1 * num)) % 4
elif cmd == 'R':
# 4번 회전하면 같은 방향
num %= 4
#방향은 4방향
robot_d = (robot_d + (3 * num)) % 4
elif cmd == 'F':
#반복 횟수만큼 한 칸씩 전진
for n in range(num):
robot_x += dx[robot_d]
robot_y += dy[robot_d]
#범위 확인
if not 0 <= robot_x < B or not 0 <= robot_y < A:
print('Robot {} crashes into the wall'.format(id))
flag = True
break
#동일 위치 로봇 확인, 로봇 딕셔너리 값을 하나씩 비교
for key, value in robots.items():
compare_x, compare_y, _ = value
if robot_x == compare_x and robot_y == compare_y:
print('Robot {} crashes into robot {}'.format(id, key))
flag = True
break
#전진 반복문 종료
if flag:
break
#명령 수행 반복문 종료
if flag:
break
#오류 발생하지 않으면, 로봇 딕셔너리에 현재 이동한 로봇 정보 업데이트하여 저장
robots[id] = (robot_x, robot_y, robot_d)
#정상 종료(오류 발생 X)시 출력
if not flag:
print('OK')
|
cs |
5. 고민
- 딕셔너리가 아니라 그냥 좌표로 처리했으면, 동일 좌표 로봇 찾는 연산이 더 줄었을 것같다.
'Algorithms > 백준' 카테고리의 다른 글
[백준_3709]레이저빔은 어디로 with Python (0) | 2021.06.01 |
---|---|
[백준_21610]마법사 상어와 비바라기 with Python (0) | 2021.05.31 |
[백준_11559]Puyo Puyo with Python (0) | 2021.05.21 |
[백준_2636] 치즈 with Python (0) | 2021.05.20 |
[백준_5430] AC with Python (0) | 2021.05.18 |
댓글