@@@ 알고리즘/백준 스터디

2174(로봇 시뮬레이션) - 해결

HTG 2021. 8. 27. 15:27
728x90

로봇 시뮬레이션

 

가로 A(1≤A≤100), 세로 B(1≤B≤100) 크기의 땅이 있다. 이 땅 위에 로봇들이 N(1≤N≤100)개 있다.

로봇들의 초기 위치는 x좌표와 y좌표로 나타난다. 위의 그림에서 보듯 x좌표는 왼쪽부터, y좌표는 아래쪽부터 순서가 매겨진다. 또한 각 로봇은 맨 처음에 NWES 중 하나의 방향을 향해 서 있다. 초기에 서 있는 로봇들의 위치는 서로 다르다.

이러한 로봇들에 M(1≤M≤100)개의 명령을 내리려고 한다. 각각의 명령은 순차적으로 실행된다. 즉, 하나의 명령을 한 로봇에서 내렸으면, 그 명령이 완수될 때까지 그 로봇과 다른 모든 로봇에게 다른 명령을 내릴 수 없다. 각각의 로봇에 대해 수행하는 명령은 다음의 세 가지가 있다.

  1. L: 로봇이 향하고 있는 방향을 기준으로 왼쪽으로 90도 회전한다.
  2. R: 로봇이 향하고 있는 방향을 기준으로 오른쪽으로 90도 회전한다.
  3. F: 로봇이 향하고 있는 방향을 기준으로 앞으로 한 칸 움직인다.

간혹 로봇들에게 내리는 명령이 잘못될 수도 있기 때문에, 당신은 로봇들에게 명령을 내리기 전에 한 번 시뮬레이션을 해 보면서 안전성을 검증하려 한다. 이를 도와주는 프로그램을 작성하시오.

잘못된 명령에는 다음의 두 가지가 있을 수 있다.

  • Robot X crashes into the wall: X번 로봇이 벽에 충돌하는 경우이다. 즉, 주어진 땅의 밖으로 벗어나는 경우가 된다.
  • Robot X crashes into robot Y: X번 로봇이 움직이다가 Y번 로봇에 충돌하는 경우이다.

입력

첫째 줄에 두 정수 A, B가 주어진다. 다음 줄에는 두 정수 N, M이 주어진다. 다음 N개의 줄에는 각 로봇의 초기 위치(x, y좌표 순) 및 방향이 주어진다. 다음 M개의 줄에는 각 명령이 명령을 내리는 순서대로 주어진다. 각각의 명령은 명령을 내리는 로봇, 명령의 종류(위에 나와 있는), 명령의 반복 회수로 나타낸다. 각 명령의 반복 회수는 1이상 100이하이다.

 

출력

첫째 줄에 시뮬레이션 결과를 출력한다. 문제가 없는 경우에는 OK를, 그 외의 경우에는 위의 형식대로 출력을 한다. 만약 충돌이 여러 번 발생하는 경우에는 가장 먼저 발생하는 충돌을 출력하면 된다.


좌표 때문에 머리 터질뻔 했다.

역시 문제를 잘 읽어야해... 

A, B가 각각 가로, 세로 길이로 우리가 흔히 쓰는 xy좌표이다.

그래서 행렬과 반대로 적용해야하며 특히, 행은 순서도 반대이다.

구현 시뮬레이션이라 크게 다른 어려운 점은 없었다. 

import sys

# 땅 크기
A, B = map(int,sys.stdin.readline().split())

total = [[0] * (A+1) for _ in range(B+1)]

# 방향에 따라 이동할 좌표 설정
dir = ["N","E","S","W"]
dirs = [(1,0),(0,1),(-1,0),(0,-1)]

# 로봇 수, 로봇의 명령 수
N, M = map(int,sys.stdin.readline().split())

# 로봇 초기 위치 및 설정
robots = [[]]
for i in range(1,N+1):
    robot = list(sys.stdin.readline().split())
    # 숫자로 바꿔서 입력
    robot[0] = int(robot[0])
    robot[1] = int(robot[1])
    # 방향을 좌표 인덱스로 변환
    robot[2] = dir.index(robot[2])
    # 로봇 숫자를 추가하여 저장
    robots.append([i] + robot)

# 좌표에 로봇 위치시키기
for i in range(1,N+1):
    total[B - robots[i][2] + 1][robots[i][1]] = robots[i][0]


# 명령 (로봇 번호, 명령 종류, 횟수)
opers = []
for _ in range(M):
    opers.append(list(sys.stdin.readline().split()))

ans = "OK"
for oper in opers:
    ck = False
    # 좌우 회전은 나머지를 사용해서 설정
    if oper[1] == "L":
        robots[int(oper[0])][3] = (robots[int(oper[0])][3] - int(oper[2])) % 4
    elif oper[1] == "R":
        robots[int(oper[0])][3] = (robots[int(oper[0])][3] + int(oper[2])) % 4
    # 전진
    elif oper[1] == "F":
        # 지금의 자리를 0으로 초기화
        total[B - robots[int(oper[0])][2] + 1][robots[int(oper[0])][1]] = 0
        # 전진하는 과정
        for _ in range(int(oper[2])):
            # 이동
            robots[int(oper[0])][2] += dirs[robots[int(oper[0])][3]][0]
            robots[int(oper[0])][1] += dirs[robots[int(oper[0])][3]][1]
            # 이동 좌표가 범위 안 일때
            if 1<= robots[int(oper[0])][2] <= B and 1<= robots[int(oper[0])][1] <= A:
                pass
            # 이동 좌표가 범위 밖 일때
            else:
                ck = True
                ans = "Robot "+oper[0]+" crashes into the wall"
                break
            # 다른 번호를 만날 때(다른 로봇과 겹침)
            if total[B - robots[int(oper[0])][2] +1][robots[int(oper[0])][1]] != 0:
                ck = True
                ans = "Robot "+oper[0]+" crashes into robot "+str(total[B - robots[int(oper[0])][2] +1][robots[int(oper[0])][1]])
                break
        if ck:
            break
        # 아무 에러 없이 통과하면 해당자리에 로봇 위치
        total[B - robots[int(oper[0])][2] + 1][robots[int(oper[0])][1]] = int(oper[0])
        
    if ck:
        break

print(ans)