[ 백준 ] 2482 / 색상환

金弘均·2021년 9월 16일
0

Baekjoon Online Judge

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

# Appreciation

/*
 * Problem :: 2482 / 색상환
 *
 * Kind :: Dynamic Programming
 *
 * Insight
 * - N 개 중에 서로 다른 K 개를 택하는 거라면
 *   nCr = (n-1)Cr + (n-1)C(r-1) 로 해서 DP로 풀텐데
 *   인접한 색상 사용 금지라니...
 *   + dp[i][j] = i 개의 색에서 인접한 색상이 아닌 j 개 색을 선택하는 경우의 수
 *     라고 한다면...
 *     dp[i][j] = dp[i-1][j] + dp[i-2][j-1] 일려나?
 *     주어진 N 개의 색 중 i 번째 색을 선택한 경우와 그렇지 않은 경우로 나누면 되니까
 *     # 그런데 위처럼 풀었더니 틀렸다!
 *       N=3, K=2 라면 논리적으로 dp 가 아래와 같아서
 *         j 0 1 2
 *       i \
 *       0   0 0 0
 *       1   1 1 0
 *       2   1 2 0
 *       3   1 3 0
 *       dp[N][K] = 0 이 나와야 되는데 1 이 나온다
 *       dp[3][2] = dp[2][2] + dp[1][1] 이니까 당연한데...
 *       왜 틀리게 나올까?
 *       -> 색상환이 원형이어서 마지막 색이랑 첫번째 색이 인접한 것을 고려해야 한다!
 *          첫번째 색의 인덱스를 1 로, 마지막 색의 인덱스를 N 으로 보면
 *          마지막 색은 1 번째 색, N-1 번째색과 인접한다
 *          따라서, 마지막 색을 사용하는 경우의 수는 dp[N-3][K-1] 이 되어야 한다
 *          마지막 색을 사용하지 않는 경우의 수는 dp[N-1][K] 일 것이니
 *          dp[N][K] = dp[N-3][K-1] + dp[N-1][K] 이다
 *          (그니까 N-1 번째 색까지만 dp 돌리면 되겠구나)
 *
 * Point
 * - 경우의 수를 10억3 으로 나누어야 한다는 것... 알지?
 */

# Code

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

#include <iostream>
#include <cstring>

using namespace std;

#define endl '\n'

// Set up : Global Variables
#define MOD 1000000003

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


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

    // Set up : Input
    int N, K;
    cin >> N >> K;

    // Process
    int dp[N][K+1]; /* dp[i][j] = i 개의 색에서
                     *            인접한 색상이 아닌 j 개 색을 선택하는 경우의 수 */
    memset(dp, 0, sizeof(dp));
    
    for (int i=1; i<=N; i++) {
        /* 초기화 */
        dp[i][0] = 1; /* 0 개의 색을 선택하는 경우의 수는 단 하나임 */
        dp[i][1] = i; /* 1 개의 색을 선택하는 경우의 수는 색의 수와 같음 */
    }
    for (int i=2; i<=N-1; i++) {
        for (int j=2; j<=K; j++) {
            /* i 번째 색을 사용하지 않는 경우 + i 번째 색을 사용하는 경우 */
            dp[i][j] = dp[i-1][j] + dp[i-2][j-1];
            dp[i][j] %= MOD;
        }
    }

    /* 마지막 색을 사용하는 경우는 인접한 색상이 2개임 */
    int ans = (dp[N-3][K-1] + dp[N-1][K]) % MOD;

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

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

0개의 댓글