본문 바로가기
PS/백준

[백준/BOJ] 2174번 - 로봇 시뮬레이션(Python)

by 행복한라이언 2023. 9. 11.
728x90
반응형

· 문제링크

https://www.acmicpc.net/problem/2174

 

2174번: 로봇 시뮬레이션

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

www.acmicpc.net

·  핵심

1. 방향에 따라 움직임 : dx-dy 테크닉 사용 

2. 격자 내 움직임  : in_range 함수로 판단

3. 편한 좌표계로 변환(convert_coordinates) 및 문자 방향 동(0)남(1)서(2)북(3)에 맞게 변환(direction)

≫ (기존) 1base의 왼쪽 하단(1, 1) - 오른쪽 상단(n, m) → (변형) 0base의 왼쪽 상단(0, 0) - 오른쪽 하단(n, m)

# 좌표계 좌표 변환(열좌표, 행좌표. 행의 수)
def convert_coordinates(c, r, R, C):
    new_r = R - 1 - r
    new_c = c
    return new_c, new_r

# 열, 행, 방향
robots =[['열', '행', '방향']] + [list(input().split()) for _  in range(N)]
for idx, robot in enumerate(robots):
    if idx != 0:
        # 1base 변환, 방향 -> cur_dir로 변경
        cc, cr = convert_coordinates(int(robot[0]) - 1,int(robot[1]) - 1, R, C)
        robots[idx] = [cc, cr, direction(robot[2])]
        board[cr][cc] = idx

4. 시뮬레이션

  1.  wall_flag와 robot_flag 도입 이유 : 벽 충돌을 체크하기 위한 wall_flag, 로봇끼리의 충돌을 체크하기 위하 robot_flag 설정 → 정상적으로 작동하는 경우를 판단(wall_flag == True && robot_flag == True)
  2.  not in_range일 때 -1, -1를 return하는 이유 : in_range가 False라는 것은 nr, nc가 격자를 벗어났다는 것이다. 출력값에 벽에 부딪힐 경우 특정 좌표 등이 필요하지 않아서 -1, -1로 출력값을 기록한다.
  3.  if board[nr][nc] != 0을 체크하는 이유: 0이 아니라는 것은 다른 로봇이 존재한다는 것을 의미한다. 또 nr, nc를 return하는 이유는 board[nr][nc]에 존재하는 로봇의 숫자가 필요하기 때문이다.
  4. 기존의 로봇이 존재하는 위치인 board[cr][cc] = 0 으로 초기화 → 현재 위치 변경 cr, cc = nr, nc→ 변경된 위치에 로봇 위치 시키기
# cr, cc 기존 위치 초기화
board[cr][cc] = 0
cr, cc = nr, nc
board[cr][cc] = robot_num

· 코드(Python)

# https://www.acmicpc.net/problem/2174
C, R = map(int, input().split())
N, M = map(int, input().split())

board = [[0 for _ in range(C)] for _ in range(R)]

# cur_dir 결정
def direction(prompt):
    if prompt == "E":
        return 0
    elif prompt == "S":
        return 1
    elif prompt == "W":
        return 2
    else:
        return 3
    
# 좌표계 좌표 변환(열좌표, 행좌표. 행의 수)
def convert_coordinates(c, r, R, C):
    new_r = R - 1 - r
    new_c = c
    return new_c, new_r

# 열, 행, 방향
robots =[['열', '행', '방향']] + [list(input().split()) for _  in range(N)]
for idx, robot in enumerate(robots):
    if idx != 0:
        # 1base 변환, 방향 -> cur_dir로 변경
        cc, cr = convert_coordinates(int(robot[0]) - 1,int(robot[1]) - 1, R, C)
        robots[idx] = [cc, cr, direction(robot[2])]
        #처음에 존재하는 로봇의 위치 기록
        board[cr][cc] = idx
        
# 로봇번호 1base, 명령어, 반복회수
cmds = [list(input().split()) for _ in range(M)]

# NameError 방지
nr, nc = 0, 0
wall_flag = True
robot_flag = True

# 동(0)남(1)서(2)북(3)
dr = [0, 1, 0, -1]
dc = [1, 0, -1, 0]

# 격자 내 이동
def in_range(r, c):
    return 0 <= r < R and 0 <= c < C

# `2개 이상일 때 로봇의 마지막 도착지를 결정할 수 있어야함.`
def simulate(robot_num, prompt, cnt, cr, cc, cur_dir):
    global nr, nc, wall_flag, robot_flag
    for _ in range(cnt):
        if prompt == "R":
            cur_dir = (cur_dir + 1) % 4
        elif prompt == "L":
            cur_dir = (cur_dir + 3) % 4
        else:
            nr = cr + dr[cur_dir]
            nc = cc + dc[cur_dir]
            if not in_range(nr, nc):
                wall_flag = False
                return robot_num, cur_dir, -1, -1
            else:
                if board[nr][nc] != 0:
                    robot_flag = False
                    return robot_num, cur_dir, nr, nc
            # cr, cc 기존 위치 초기화
            board[cr][cc] = 0
            cr, cc = nr, nc
            board[cr][cc] = robot_num
    return robot_num, cur_dir, cr, cc
                
for cmd in cmds:
    # 로봇번호(int), 명렁어(string), 반복회수(int)
    robot_num, prompt, cnt = int(cmd[0]), cmd[1], int(cmd[2])
    # 로봇의 위치 : 열(int), 행(int), 방향(int)
    cc, cr, cur_dir = robots[robot_num][0], robots[robot_num][1], robots[robot_num][2]
    robot_num, cur_dir, nr, nc = simulate(robot_num, prompt, cnt, cr, cc, cur_dir)
    if not robot_flag:
        print(f"Robot {robot_num} crashes into robot {board[nr][nc]}")
        break
    if not wall_flag:
        print(f"Robot {robot_num} crashes into the wall")
        break
    # 이동 후 위치 기록
    robots[robot_num] = [nc, nr, cur_dir]
    
if wall_flag and robot_flag:
    print("OK")

 

728x90
반응형