[ 백준 ] 1189 / 컴백홈

金弘均·2021년 9월 15일
0

Baekjoon Online Judge

목록 보기
117/228
post-thumbnail

# Appreciation

/*
 * Problem :: 1189 / 컴백홈
 *
 * Kind :: DFS + Brute Force
 *
 * Insight
 * - max(R), max(C) <= 5 이다
 *   브루트 포스로 풀더라도 정말 웬만해서는 시간 제한이 걸리지 않을 정도로 작은 값이다
 *   # 한번 지나친 곳을 다시 방문하지 않는다니,
 *     DFS 로 다 돌아보면서 그때그때 방문처리 잘 해주고
 *     주어진 거리가 되면 그 곳이 집인지 확인해주는 식으로 구현하면 충분할 것 같다
 *
 * Point
 * - 방문처리시, 이전 칸으로 돌아갈 때
 *   현재 칸을 방문하지 않은 칸으로 되돌려 주는 걸 잊지 말자
 *
 * - 거리가 실제로 이동한 거리(출발칸 포함하지 않음)가 아니라
 *   거쳐간 칸의 개수(출발칸 포함)이다
 *   + 즉, 시작한 칸이 집이라고 하면 
 *     거리가 0 이 아니라 1 로 간주해야 한다
 */

# Code

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

#include <iostream>

using namespace std;

#define endl '\n'

// Set up : Global Variables
int R, C, K;
char board[5][5];
bool isVisited[5][5];
int dy[4] = {+1, 0, 0, -1};
int dx[4] = {0, +1, -1, 0};

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


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

    // Set up : Input
    cin >> R >> C >> K;
    for (int i=0; i<R; i++) {
        for (int j=0; j<C; j++) {
            cin >> board[i][j];
        }
    }
    /* 집의 좌표를 빈칸('.')과 이동불가칸('T')으로부터 구별되는 'H'로 설정
     * 집의 좌표를 전역변수 처리하기 귀찮고, 좌표끼리 비교하는 것도 귀찮아서 그렇게 함 */
    board[0][C-1] = 'H';

    // Process
    /* DFS 돌림 */
    int ans = dfs(R-1, 0, 1);

    // Control : Output
    cout << ans << endl;
}

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

int dfs(int cy, int cx, int dist)
/* 현재 좌표에서 집까지 도착하는 경우중 거리가 K+1-dist 인 가짓수를 반환
 * 현재 좌표 = (cy, cx), 현재 이동한 거리 = dist */
{
    /* 현재 이동한 거리가 K 이면 */
    if (dist == K) {
        /* 현재 좌표가 집이면 1을 반환(가짓수 하나 찾음), 그렇지 않으면 0을 반환 */
        return (board[cy][cx] == 'H') ? 1 : 0;
    }

    /* 현재 좌표 방문 처리 */
    isVisited[cy][cx] = true;
    int ret = 0; /* 현재 좌표에서 출발하여 집으로 가는 거리가 K+1-dist 인 가짓수 */

    for (int i=0; i<4; i++) {
        int ny = cy + dy[i];
        int nx = cx + dx[i];
        /* 좌표가 유효하고, 방문되지 않았고, 이동불가칸이 아니면 */
        if (isValid(ny, nx) && not(isVisited[ny][nx]) && board[ny][nx] != 'T') {
            /* 그 칸으로 이동 */
            ret += dfs(ny, nx, dist+1);
        }
    }

    /* 현재 좌표 비(非)방문 처리 */
    isVisited[cy][cx] = false;
    return ret;
}
profile
이런 미친 게임을 봤나! - 옥냥이

0개의 댓글