ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 백준 2482번 : 색상환
    알고리즘 공부 2020. 4. 30. 17:28

      이 문제가 약간 까다로운 이유는 고리 형태이기 때문에 처음과 끝이 이어져있기 때문이다. 그래서 인접했는지를 판단할 때 처음과 끝을 특수하게 새로 판단해줘야 하는데 나는 이 부분을 처음에는 고려하지 않고 나중에 출력할 때만 고려함으로써 깔끔하게 풀었다.


      역시 dp문제이므로 dp를 잘 정의해보자.

     

    dp[n][k] : n개의 색일렬로 있을 때, k개의 색인접하지 않게 고르는 경우의 수

     

      여기서 포인트는 문제의 상황과는 다르게 일렬로 있을 때로 dp를 설정하는 것이다. 이 dp를 구하는 방법은 어렵지 않다. n-1개의 색이 있는 상태에서 제일 끝에 하나의 색을 추가한다고 가정해보자. 그럼 상황은 두 가지로 나뉜다.

     

    1. n번째 색을 선택하는 경우

    2. n번째 색을 선택하지 않는 경우

     

      1. n번째 색을 선택하는 경우 인접하지 못한다는 조건에 의해 n-1번째 색은 절대로 선택할 수 없다. 따라서 n-2개의 색에서 k-1개를 고르면 되므로 dp[n-2][k-1]이다. 2. n번째 색을 선택하지 않는 경우 n번째 색이 없는 것과 마찬가지 이므로 n-1개의 색에서 k개를 고르면 되므로 dp[n-1][k]이다.

     

    dp[n][k] = dp[n-2][k-1] + dp[n-1][k]

     

      그러면 마지막에 이 일렬로 배열되어 있는 상황을 어떻게 고리로 변형시키느냐는 문제만 남았다. 의외로 간단하다. n개의 색 고리가 있을 때 1. 첫 번째 색(12시 방향에 있는 색)을 고른다고 가정해보자. 그러면 그 색을 포함해 왼쪽 색과 오른쪽 색은 자동적으로 고를 수 없다. 그러므로 일렬로 있을 때 n-3개의 색에서 k-1개의 색을 고르는 것과 동일해진다. 2. 첫번째 색을 고르지 않는다고 가정해보면 렬로 있을 때 n-1개의 색에서 k개의 색을 고르는 것과 동일해진다.

     

    circle_dp[n][k] = dp[n-3][k-1] + dp[n-1][k]

     

    #include <iostream>
    
    using namespace std;
    
    int n, k;
    int dp[1002][1002];
    int DIV = 1000000003;
    
    int main()
    {
        cin >> n >> k;
        
        for(int i = 0; i <=n ; i++) dp[i][0] = 1;
        
        dp[1][1] = 1;
        
        for(int i = 2; i <= n; i++)
        {
            for(int j = 1; 2 * j <= i + 1; j++)
            {
                dp[i][j] = (dp[i-2][j-1] + dp[i-1][j]) % DIV;
            }
        }
        
        cout << (dp[n-3][k-1] + dp[n-1][k]) % DIV;
    
        return 0;
    }

    '알고리즘 공부' 카테고리의 다른 글

    백준 2662번 : 기업투자  (0) 2020.05.02
    백준 1563번 : 개근상  (0) 2020.05.01
    백준 2624 : 동전 바꿔주기  (0) 2020.04.28
    백준 2602번 : 돌다리 건너기  (0) 2020.04.27
    백준 1328번 : 고층 빌딩  (0) 2020.04.26
Designed by Tistory.