본문 바로가기

Problem Solving/boj

[BOJ] 3987. 보이저 1호(Python) / Simulation

www.acmicpc.net/problem/3987

 

3987번: 보이저 1호

첫째 줄에 시그널을 보내는 방향을 출력한다. (U: 위, R: 오른쪽, D: 아래, L: 왼쪽) 만약, 방향이 여러 가지가 존재한다면, U, R, D, L의 순서 중 앞서는 것을 출력한다. 둘째 줄에는 가장 긴 시간을 출

www.acmicpc.net

실버2 문제임에도 나를 꽤나 괴롭혔던 시뮬레이션 문제다. 문제 푸는 데 1시간, 디버깅 1시간.

  • Input 받으면서 벽을 블랙홀("C")로 둘러싼다.
    • 이는 코드를 줄이고 종료조건을 좀더 깔끔하게 하기 위함이다. 
  • 상하좌우 시작 4방향으로 for문 돌리며 종료 조건 만날 때까지 While문으로 이동을 제어한다.
    • 블랙홀 만나면 while문 탈출
    • 행성 만날 경우 종류별로 현재 방향별로 다음 방향 전환
    • 처음 출발 지점과 처음 방향으로 되돌아오면 무한루프이므로 그 때의 방향과 "Voyager" 문구 출력
  • While문이 끝나면 최댓값을 갱신했던 그 때의 방향과 이동 시간을 출력한다.

 

파이썬 코드는 다음과 같다.


import sys
input = sys.stdin.readline

direction = ("U", "R", "D", "L")
dr = (-1, 0, 1, 0)
dc = (0, 1, 0, -1)
P, Q = (1, 0, 3, 2), (3, 2, 1, 0)

N, M = map(int, input().split())
A = [["C"] * (M+2)]     # 블랙홀로 둘러싸기
for _ in range(N):
    A.append(["C"] + list(input().strip()) + ["C"])
A.append(["C"] * (M+2))
sr, sc = map(int, input().split())

def solve():
    max_time, max_dir = 0, 0
    for sd in range(4):
        r, c, d, time = sr, sc, sd, 1   # 시작 위치, 시작 방향, 이동 시간
        while True:
       		# 블랙홀 만났거나 항성계 벗어나면
            if A[r+dr[d]][c+dc[d]] == "C":
                break
            
            r += dr[d]
            c += dc[d]

            # 방향 전환
            if A[r][c] == "/":
                d = P[d]
            elif A[r][c] == "\\":
                d = Q[d]
            time += 1

            # 처음 출발한 지점을 동일한 방향으로 접근한 경우 무한 루프
            if (r, c, d) == (sr, sc, sd):
                print(direction[sd])
                print("Voyager")
                return

        # 값이 클 때만 이동 시간, 현재 방향 갱신
        if max_time < time:
            max_time = time
            max_dir = sd

    print(direction[max_dir])
    print(max_time)

solve()

  • 시간 : 152ms / 메모리 : 131640KB
  • 고찰 : 코드 칠 때 신중하게 치자. 그 전에, 설계단계에서 완벽하게 코드의 구조가  머릿 속에 들어와야 한다. 그 때야 비로소 코드로 옮길 타이밍이 된 것이다. 잔 실수를 줄이자. 디버깅에 너무 의존하지 말고, 처음 짤 때 잘 짜자. 그게 실력이다.