본문 바로가기
Algorithms/백준

[백준_2174]로봇 시뮬레이션 with Python

by jeomn 2021. 5. 26.

백준(BOJ) 시뮬레이션: 로봇 시뮬레이션(골드 5)

문제 출처: https://www.acmicpc.net/problem/2174

 

2174번: 로봇 시뮬레이션

첫째 줄에 두 정수 A, B가 주어진다. 다음 줄에는 두 정수 N, M이 주어진다. 다음 N개의 줄에는 각 로봇의 초기 위치(x, y좌표 순) 및 방향이 주어진다. 다음 M개의 줄에는 각 명령이 명령을 내리는 순

www.acmicpc.net

 

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 = [-1010]
    dy = [0-101]
    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. 고민

  • 딕셔너리가 아니라 그냥 좌표로 처리했으면, 동일 좌표 로봇 찾는 연산이 더 줄었을 것같다.

댓글