SWEA 14362 - 무한 로봇 D-Ⅳ



이 문제는 SWEA 문제입니다. 문제 출처 : 무한 로봇



🔥 주의할 점



k번째로 명령을 수행한 직후의 위치를 PkP_{k}라고 할 때, PkP_{k}는 모든 좌표를 의미한다.
로봇이 이동을 마치고 난 후의 점이 아닌 이동 중 마주한 모든 정수 좌표들을 의미한다.



💥 How to Solve?



결과부터 말하자면, 테스트 케이스는 125개, 최대 움직임은 2500회이다.
내가 구현한 방법은 움직임이 Worst Case인 경우 총 4번을 반복해야하니 10000회 이루어지고,
모든 TC가 10000회 이루어진다해도 125만회로 제한 시간 3초 이내에 해결할 수 있다고 판단해 단순 구현 방법으로 해결했다.



‼ Point ‼



우선 용어 몇 가지를 정의하고 시작한다.

| | | | | |


오른쪽으로 회전한다면 배열에서 +1 만큼 되고, 왼쪽으로 회전한다면 배열에서 -1 만큼 되는 형태로 회전에 따른 방향을 정해둔다.



움직임 : 로봇이 움직인 방향을 기록한 데이터

초기 방향 : Right

시작 방향 : 첫 움직임 방향 - ex) RS 라고 한다면 맨 처음 Right에서 오른쪽으로 돌고 움직이기 때문에 Down이 된다. 즉 시작 방향은 Down이다.

마지막 방향 : 로봇이 마지막으로 이동한 방향, 움직임에 마지막에 해당하는 값이다.

로봇은 특정 움직임으로 반복하게 된다. 그 종류는 아래와 같다.


1️⃣) 움직임이 없는 경우. ex) LLLLL

2️⃣-1️⃣) 초기 방향(Right)과 마지막 진행 방향이 같고, 마지막 위치가 원점이 아닌 경우 - 끝없이 뻗어나가게 된다. ex) S, RSL

2️⃣-2️⃣) 초기 방향(Right)과 마지막 진행 방향이 같고, 마지막 위치가 원점인 경우 - 움직임을 계속 반복하기 때문에 다른 점들을 방문하진 않는다.

3️⃣) 초기 방향(Right)과 마지막 진행 방향(Left)이 반대인 경우 - 움직임을 정확히 반대로 진행한다. ex) 움직임이 Right, UP, Left, Up, Left 이라면 => Left, Down, Right, Down, Right 를 거쳐 원점으로 돌아온다.

4️⃣) 초기 방향(Right)과 마지막 진행 방향(Up)인 경우 - 움직임을 **반 시계 방향(방향이 왼쪽으로 회전)**으로 돌면서 진행한다.
ex) SLS -> 움직임 : Right, Up => Up, Left => Left, Down => Down, Right
위와 같은 움직임을 거쳐 원점으로 돌아온다.


5️⃣) 초기 방향(Right)과 마지막 진행 방향(Down)인 경우 - 움직임을 **시계 방향(방향이 오른쪽으로 회전)**으로 돌면서 진행한다.
ex) SRS -> 움직임 : Right, Down => Down, Left => Left, Up => Up, Right
위와 같은 움직임을 거쳐 원점으로 돌아온다.


글로는 이해가 어려우니 그림을 통해 이해해보자.


Left


Left


Left


위와 같이 좌표를 이동하면서 가장 먼 좌표 값을 기억해두면 답을 구할 수 있다.

✨ Python Code



"""
문제 출처 : https://swexpertacademy.com/main/code/problem/problemDetail.do?contestProbId=AYCne646vKQDFARx&categoryId=AYCne646vKQDFARx&categoryType=CODE&problemTitle=&orderBy=FIRST_REG_DATETIME&selectCodeLang=ALL&select-1=&pageSize=10&pageIndex=1
0 : right
1 : down
2 : left
3 : up
dir = [0,0,0,0]  : 각 방향에 대한 움직임 횟수 저장
index+1 => Right
index-1 => Left
"""
T = int(input())
dxdy = {0:[1,0], 1: [0, -1], 2: [-1,0], 3:[0,1]}
for t in range(1, T+1):
    move = input()
    direction = 0
    x, y = 0, 0
    max_value = 0
    path = []
    for m in move:
        if m == 'S':
            path.append(direction)
            dx, dy = dxdy[direction]
            x, y = x + dx, y + dy
            max_value = max_value if max_value > x**2+y**2 else x**2+y**2
        elif m == 'L':
            direction = (direction + 3) % 4
        elif m == 'R':
            direction = (direction+1)%4

    ## 1. 움직임이 없는 경우
    if len(path) == 0:
        print("#{} {}".format(t, max_value))
        continue

    last_dir = direction
    ## 2-1 초기 방향과 마지막 진행 방향이 같고, 원점 - 움직임 반복
    if x == 0 and y == 0:
        print("#{} {}".format(t, max_value))
        continue
    ## 2-2 초기 방향과 마지막 진행 방향 같고 원점 아닌 경우 - 끝없이 뻗어나간다.
    if last_dir == 0:
        print("#{} {}".format(t, "oo"))
        continue
    ## 3. 마지막 진행 방향이 Down인 경우 - 움직임 시계 방향으로 3번 반복 진행
    elif last_dir == 1:
        for i in range(1,4):
            for p in path:
                p = (p + i) % 4
                dx, dy = dxdy[p]
                x, y = x + dx, y + dy
                max_value = max_value if max_value > x ** 2 + y ** 2 else x ** 2 + y ** 2
    ## 4. 마지막 진행 방향이 Left인 경우 - 움직임 반대로 한 번 반복
    elif last_dir == 2:
        for p in path:
            p = (p+2)%4
            dx, dy = dxdy[p]
            x, y = x+dx, y+dy
            max_value = max_value if max_value > x**2+y**2 else x**2+y**2
    ## 5. 마지막 진행방향이 Right인 경우 - 움직임 반 시계 방향으로 3번 반복 진행
    elif last_dir == 3:
        for i in range(1,4):
            for p in path:
                p = (p + (4-i)) % 4
                dx, dy = dxdy[p]
                x, y = x + dx, y + dy
                max_value = max_value if max_value > x ** 2 + y ** 2 else x ** 2 + y ** 2
    print("#{} {}".format(t, max_value))



끝 !!


✨ 잘못된 부분은 많은 조언 및 지적 부탁드립니다. - JunHyxxn