[ 백준 ] 17836 / 공주님을 구해라!

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
71/228
post-thumbnail

# Appreciation

/*
 * Problem :: 17836 / 공주님을 구해라!
 *
 * Kind :: BFS
 *
 * Insight
 * - 그람을 갖고 있지 않으면 벽을 못 부수지만
 *   그람을 가지고 있으면 벽을 부수고 갈 수 있다
 *   + 현재 그람을 가지고 있는지 그렇지 않은지를 주의하며 BFS 를 돌리자
 *     dp[i][j][GRAM] = 그람을 가지고 (i,j) 위치에 도달하는 최소시간
 *                      초기값은 -1(도달하지 못한 경우)
 *     dp[i][j][NOGRAM] = 그람을 가지지 않고 (i,j) 위치에 도달하는 최소시간
 *                        초기값은 -1(도달하지 못한 경우)
 *
 * Point
 * - '이내' = '안(일정한 표준이나 한계를 넘지 않은 정도'
 *   + 20자 이내 = (한 자에서부터) 이십 자까지
 *   + T시간 이내 = (한 시간에서부터) T 시간까지
 */

# Code

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

#include <iostream>
#include <queue>
#include <cstring>

using namespace std;

#define endl '\n'

// Set up : Global Variables
struct Point { int y, x, hasGram; };
enum { NOGRAM, GRAM};
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};

// Set up : Functions Declaration
/* None */


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

    // Set up : Input
    int N, M, T;
    cin >> N >> M >> T;
    int A[N+1][M+1];
    for (int i=1; i<=N; i++)
        for (int j=1; j<=M; j++)
            cin >> A[i][j];

    // Process
    queue<Point> que;
    int dp[N+1][M+1][2];
    memset(dp, -1, sizeof(dp));

    /* 초기화 - (1,1) 위치 */
    dp[1][1][NOGRAM] = 0;
    que.push({1, 1, NOGRAM});

    /* BFS */
    while (not(que.empty())) {
        int cy = que.front().y; /* 현재 y 좌표 */
        int cx = que.front().x; /* 현재 x 좌표 */
        int hasGram = que.front().hasGram; /* 현재 그람 소유 여부 */
        que.pop();

        /* 현재 위치에 그람이 있다면 */
        if (A[cy][cx] == 2) {
            hasGram = true; /* 줍줍 */
            /* 이제부터는 그람으로 벽을 부수면서 전진 */
            dp[cy][cx][GRAM] = dp[cy][cx][NOGRAM];
        }
        /* 공주님 발견 */
        if (cy == N && cx == M) continue;

        for (int i=0; i<4; i++) {
            int ny = cy + dy[i]; /* 다음 y 좌표 */
            int nx = cx + dx[i]; /* 다음 x 좌표 */
            /* 다음 (ny,nx) 위치가 유효하다면 */
            if (ny >= 1 && ny <= N && nx >= 1 && nx <= M) {
                /* 그람을 가지고 있다면 */
                if (hasGram) {
                    /* (ny,nx) 위치에 방문하지 않았거나 더 빨리 도착하는 경우라면 */
                    if (dp[ny][nx][GRAM] == -1
                        || dp[ny][nx][GRAM] > dp[cy][cx][GRAM]+1)
                    {
                        dp[ny][nx][GRAM] = dp[cy][cx][GRAM]+1; /* dp 갱신 */
                        que.push({ny, nx, GRAM}); /* que 에 추가 */
                    }
                /* 그람을 가지고 있지 않다면 */
                } else {
                    /* (ny,nx) 위치가 벽이 아니며 */
                    if (A[ny][nx] != 1) {
                        /* (ny,nx) 위치에 방문하지 않았거나 더 빨리 도착하는 경우라면 */
                        if (dp[ny][nx][NOGRAM] == -1
                            || dp[ny][nx][NOGRAM] > dp[cy][cx][NOGRAM]+1)
                        {
                            dp[ny][nx][NOGRAM] = dp[cy][cx][NOGRAM]+1; /* dp 갱신 */
                            que.push({ny, nx, NOGRAM}); /* que 에 추가 */
                        }
                    }
                }
            }
        }
    }

    int INF = T+1;
    int t1 = dp[N][M][NOGRAM]; /* 그람없이 공주님을 발견할 수 있는 최단시간 */
    if (t1 == -1) { t1 = INF; } /* 발견할 수 없다면 INF 시간 */
    int t2 = dp[N][M][GRAM]; /* 그람있시 공주님을 발견할 수 있는 최단시간 */
    if (t2 == -1) { t2 = INF; } /* 발견할 수 없다면 INF 시간 */
    bool isPossible = min(t1, t2) <= T;

    // Control : Output
    cout << ((isPossible) ? to_string(min(t1, t2)) : "Fail") << endl;
}

// Helper Functions
/* None */
profile
이런 미친 게임을 봤나! - 옥냥이

0개의 댓글