# 2714 로봇 시뮬레이션
# A,B, A은 가로, B는 세로 N은 로봇들
# L,R,F : 로봇기준 왼쪽 90도, 로봇방향 기준 오른쪽 90도, 로봇 기준 앞으로 GO
# 잘못된 명령 : Robot X crashes into the wall: X번 로봇이 벽에 충돌
# Robot X crashes into robot Y : X번 로봇이 Y번 로봇에 부딪힘
def rotate_dire(rotate,current):
    dire_left = [3,0,1,2]
    dire_right = [1,2,3,0]
    if rotate == 'L':
        return dire_left[current]
    else:
        return dire_right[current]


def display_crash(flag,*numbers):
    if flag:
        return f'Robot {numbers[0]} crashes into the wall'
    else:
        return f'Robot {numbers[0]} crashes into robot {numbers[1]}'


A,B = map(int,input().split())
N,M = map(int,input().split())
robots = {}
robot_place = {}
#  E : 0 , S : 1 , W : 2 , N : 3
dire_match = {'E':0,'S':1,'W':2,'N':3}
for robot_number in range(1,N+1):
    X,Y,dire = input().split()
    robots[robot_number]= (int(X),int(Y),dire_match[dire])
    robot_place[(int(X),int(Y))] = robot_number
command_list = []
for _ in range(M):
    robot_number,command,repeat = input().split()
    command_list.append((int(robot_number),command,int(repeat)))

flag = True
result = 'OK'
go_robots = [(1,0),(0,-1),(-1,0),(0,1)]


while command_list:
    command_robot,command,repeat = command_list.pop(0)
    cu_X, cu_Y,cu_dire = robots[command_robot]
    del robot_place[(cu_X,cu_Y)]
    for _ in range(repeat):
        if command == 'F':
            next_X = cu_X + go_robots[cu_dire][0]
            next_Y = cu_Y + go_robots[cu_dire][1]
            if 1<= next_X <= A  and 1<= next_Y <= B:
                if robot_place.get((next_X,next_Y)):
                    flag = False
                    result = display_crash(False,command_robot,robot_place[(next_X,next_Y)])
                    break
                else:
                    cu_X = next_X
                    cu_Y = next_Y

            else:
                flag = False
                result = display_crash(True,command_robot)
                break 
        else:
            cu_dire = rotate_dire(command,cu_dire)

    robots[command_robot] = (cu_X,cu_Y,cu_dire)
    robot_place[(cu_X,cu_Y)] = command_robot
    if not flag:
        break


print(result)

이 문제는 구현,시뮬레이션 문제이고 문제에 주어진 조건대로, 진행시키면 되는 문제이다.

여기서 자주 쓰이는 것들은 함수화, 딕셔너리화 해서 편하게 할 수 있도록 진행했다.

먼저 방향을 숫자로 매핑시켜줬다. 그래야 방향전환시 쉽게 찾을수 있기 때문이다.

그래서 나는 E : 0 , S : 1 , W : 2 , N : 3 으로 각각 매핑시켜두었다. 

이렇게 하고 방향 전환은 rotate_dire라는 함수를 만들어, 오른쪽 왼쪽일때 각각의 리스트를 만들어주고, 방향의 숫자에 맞춰 방향변경시 변경되는 방향을 넣어두었다.

 

그 다음으로는 이 문제는 2차원 리스트를 통해 구현하는게 일반적인데, 저 같은 경우엔 해당 2차원 리스트에 저장되어있는 정보들이 극히 일부분이고, 무엇보다, 문제에 주어진 행렬은 우리가 일반적으로 만드는 리스트와 상하반전이기때문에, 딕셔너리를 통해 robot들의 정보와 위치정보를 저장시켜주었다.

 

리스트를 이용해 풀 사람들은 이동방향시 이동하는 위치를 S,N이 바뀌는것만 주의하면 됩니다.

 

 

먼저 robots라는 딕셔너리에는 각각의 로봇넘버를 키로 두고 그 안에는 위치정보와 방향정보를 넣어주었다.

그리고 robot_place라는 딕셔너리에는 로봇들의 위치정보를 키로 두고 그 안에 로봇의 넘버를 넣어주었다.

 

 

그 다음에는 동서남북을 go_robots 이라는 변수에 저장시켜줬으며, 우리가 위에 매핑시켜놓은 숫자에 맞춰서, 이동을 다음과 같이 [(1,0),(0,-1),(-1,0),(0,1)] 구현해놨다.

 

 

 

이렇게 사전작업을 해둔뒤, 우리가 저장해놓은 command들을 순차적으로 진행시키면 되는 문제이다.

 

먼저 cu_X,cu_Y,cu_dire 현재의 로봇의 정보를 가져온다. 그리고 난뒤 robot_place에서 해당 위치의 정보를 삭제해준다. 왜냐하면 이동시 robot_place을 기준으로 이동을 탐색하기 때문에, 삭제를 해주는것이다.

 

그리고 난뒤 명령어가 F일때에는 로봇의 방향으로 전진하는 것이기 때문에, 우리가 만들어놓은 go_robots을 통해 이동시켜주고, 범위가 넘어가지 않는지, 그리고 robot_place에 이미 이동할려는 위치에 로봇이 존재하는지 판단해준다.

 

그리고 그 결과에 따라, 아무 이상없이 진행되면 cu_X,cu_Y를 next_X,next_Y로 변경시켜준다.

 

만약 충돌이 발생시에는 발생경우에 따라 다르게 출력될수 있도록 만든 display_crash를 통해 해주는데, 상황에 따라  함수의 input값이 2개가 될수 있으므로, 가변인자를 통해 구현해주었습니다.

 

명령어가 'L','R'일때에는 rotate_dire라는 함수를 실행시켜 방향을 변경시켜줍니다.

 

 명령어를 수행 하고 난뒤에는 robots와 robot_place 딕셔너리에 마지막으로 변경된 값들을 저장해주면 됩니다.

 

 

모든 명령어를 수행하고 아무 에러가 없을때에는 result의 기본값인 OK가 출력되도록 하고, 아닐시에는 에러 메시지가 출력되도록 구현했습니다.

'알고리즘 > 백준' 카테고리의 다른 글

[BOJ/백준] 14499 주사위 굴리기  (0) 2021.01.29
[BOJ/백준] 9633 N-queen  (0) 2021.01.28
[BOJ/백준] 12851 숨바꼭질 2  (0) 2021.01.25
[BOJ/백준] 2133 타일 채우기  (0) 2021.01.24
[BOJ/백준] 2251 물통  (0) 2021.01.23

+ Recent posts