[ 백준 ] 13302 / 리조트

金弘均·2021년 9월 16일
0

Baekjoon Online Judge

목록 보기
221/228
post-thumbnail

# Appreciation

/*
 * Problem :: 13302 / 리조트
 *
 * Kind :: Dynamic Programming
 *
 * Insight
 * - min([첫번째 날, 쿠폰 0개])
 *   = min({하루 이용권 + [두번째 날, 쿠폰 0개],
 *          연속 3일권 + [네번째 날, 쿠폰 1개],
 *          연속 5일권 + [여섯번째 날, 쿠폰 2개]})
 *   + DP 로 풀어야 겠구나
 *     dp[n][c] = n번째 날, 쿠폰 c개를 가지고 N번째 날까지 KOI 리조트를 이용했을 때 최소비용
 *     # 쿠폰이 3개 이상이면 하루 이용권 한 장으로 교환할 수 있으므로
 *       쿠폰 3장 + [n+1번째 날, 쿠폰 c-3개] 도 생각해주자
 *
 * Point
 * - dp[n][c] 가 음수인 경우는 불가능하므로
 *   이전에 방문했는지를 -1 로 확인할 수 있다
 */

# Code

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

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

#define endl '\n'

// Set up : Global Variables
int N, M;
bool isImpossible[100+1];
int dp[100+1][40+1];

// Set up : Functions Declaration
int f(int n, int c);


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<M; i++) {
        int d; cin >> d;
        isImpossible[d] = true; /* d 일에는 리조트에 갈 수 없다는 뜻 */
    }

    // Process
    memset(dp, -1, sizeof(dp)); /* dp 초기화 */
    int ans = f(1, 0);

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

// Helper Functions
int f(int n, int c)
/* n번째 날, 쿠폰 c개를 가지고 N번째 날까지 KOI 리조트를 이용했을 때 최소비용을 반환 */
{
    /* n > N 이면 N번째 날까지 KOI 리조트를 이용했다는 뜻이기에
     * 추가 비용은 없고 탐색을 종료해야하므로 0 을 반환 */
    if (n > N) return 0;
    /* 이전에 방문된적 있으면 계산된 dp[n][c] 를 반환 */
    if (dp[n][c] != -1) return dp[n][c];
    /* n번째 날에 리조트에 갈 수 없다면 n+1번째 날을 탐색 */
    if (isImpossible[n]) return dp[n][c] = f(n+1, c);

    dp[n][c] = min({
        10000 + f(n+1, c), /* 하루 이용권 구매 */
        25000 + f(n+3, c+1), /* 연속 3일권 구매 */
        37000 + f(n+5, c+2), /* 연속 5일권 구매 */
    });
    if (c >= 3) {
        dp[n][c] = min(dp[n][c], f(n+1, c-3)); /* 쿠폰 3장 사용해서 하루 이용권 구매 */
    }
    return dp[n][c];
}
profile
이런 미친 게임을 봤나! - 옥냥이

0개의 댓글