[ 백준 ] 3987 / 보이저 1호

金弘均·2021년 9월 14일
0

Baekjoon Online Judge

목록 보기
2/228
post-thumbnail
post-custom-banner

# Appreciation

/*
 * Problem :: 3987 / 보이저 1호
 * 
 * Kind :: Simulation
 *
 * Insight
 * - 꽤 까다롭다...
 *   + 방향전환
 *     칸의 종류에 따른 로직 처리
 *     좌표 및 방향까지 고려한 방문 처리
 *     # 하나하나씩 고려해주자
 *
 * Point
 * - 초기 방향만 다를 뿐 시간을 구하는 로직은 네 방향 모두 같다
 *   + 반복문으로 처리도 가능하지만 블랙홀같이 바로 return 이 필요한 로직이 있으므로
 *     함수로 써주는게 아무래도 좋은 것 같다
 *     # 사실 처음에 반복문을 써서 풀었는데 디버깅이 어려웠다...
 *       -> 요즘 변수명도 짧아지고 함수 안쓰고 main 내에 모든 로직을 구현하느 것 같은데 지양하자
 */

# Code

//
//  BOJ
//  ver.C++
//
//  Created by GGlifer
//
//  Open Source

#include <iostream>
#include <cstring>

using namespace std;

#define endl '\n' << flush

// Set up : Global Variables
enum { U, R, D, L };
int N, M;
#define MAX 500
char G[MAX][MAX];
int dy[4] = {-1, 0, +1, 0};
int dx[4] = {0, +1, 0, -1};
int T[4][2] = {
        {R, L},
        {U, D},
        {L, R},
        {D, U}
};
#define INF 987654321

// Set up : Functions Declaration
bool isValid(int y, int x);
int getTime(int cy, int cx, int cd);


int main()
{
    // Set up : I/O
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    // Set up : Input
    cin >> N >> M;
    for (int i=0; i<N; i++)
        for (int j=0; j<M; j++)
            cin >> G[i][j];
    int PR, PC;
    cin >> PR >> PC;

    // Process
    int sy = PR-1, sx = PC-1; /* 보이저 1호 초기 위치 */

    int ans_dir = -1, ans_time = -1;
    for (int sd=0; sd<4; sd++) { /* 보이저 1호 초기 방향 <= U, R, D, L 순서 */
        int tmp_time = getTime(sy, sx, sd); /* 초기 방향에 따른 걸린 시간 */
        if (ans_time == -1 || ans_time < tmp_time) {
            ans_dir = sd;
            ans_time = tmp_time;
            if (ans_time == INF) break;
        }
    }

    // Control : Output
    switch (ans_dir) {
        case 0: cout << 'U' << endl; break;
        case 1: cout << 'R' << endl; break;
        case 2: cout << 'D' << endl; break;
        case 3: cout << 'L' << endl; break;
    } cout << ((ans_time == INF) ? "Voyager" : to_string(ans_time)) << endl;
}

// Helper Functions
bool isValid(int y, int x)
/* 주어진 좌표 (y,x) 가 유효하면 true 를 반환, 그 외 false 를 반환 */
{
    return y >= 0 && y < N && x >= 0 && x < M;
}

int getTime(int cy, int cx, int cd)
/* 좌표 (cy,cx) 에서 cd 방향으로 시그널을 보냈을 때 걸린 시간 */
{
    bool isVisited[N][M][4]; /* 좌표 및 방향까지 고려 */
    memset(isVisited, false, sizeof(isVisited));

    int time = 0;
    while (isValid(cy, cx)) { /* 시그널이 항성계 내부에 있는 동안 */
        if (isVisited[cy][cx][cd]) return INF; /* 지나간 곳을 재 방문시 무한루프 */
        isVisited[cy][cx][cd] = true;

        if (G[cy][cx] == 'C') break; /* 블랙홀을 만나면 시그널 소멸 */
        time++; /* 걸린 시간 증가 */

        switch (G[cy][cx]) { /* 행성을 만나면 방향 전환 */
            case '/': cd = T[cd][0]; break;
            case '\\': cd = T[cd][1]; break;
        }

        /* 시그널 이동 */
        cy += dy[cd];
        cx += dx[cd];
    }

    return time;
}
profile
이런 미친 게임을 봤나! - 옥냥이
post-custom-banner

0개의 댓글