ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 숫자구슬 (boj 2613)
    알고리즘 2020. 6. 5. 01:46
    728x90

    숫자구슬 문제는 Parametric search 기법을 활용해서 풀 수 있어요. 용돈관리 문제랑 상당히 유사하고 코드도 거의 똑같습니다만..

    약간의 함정이 숨어있어요.

    M개의 그룹으로 나누고 각 그룹에 속한 원소의 수를 출력해줘야하는데

     

    입력으로

    8 5
    1000 1 1 1 1 1 1 1

     

    같이 극단적으로 큰 값을 주게 되면, 용돈관리 코드로는

     

    1000
    1 7

    과 같이 그룹이 5개가 아니라 2개만 나오게 돼요

    그래서 충분히 적은 수의 그룹을 만들 수 있더라도 M개에 미치지 못한다면 적절히 쪼개주는 작업이 필요하답니다.

    쪼개는건 사실 쉬워요. 원소의 갯수가 2 이상인 그룹을 찾아서 1개씩 뽑아주면 됩니다. 뽑아주는 과정은 그룹의 갯수가 M이 될때까지 반복하는거구요.

     

    코드

    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <stack>
    
    #define INF 987654321
    
    int N, M;
    int arr[310];
    int max = 30000;
    int min;
    std::vector<int> result;
    
    
    int parametricSearch(int k) {
        int val = k;
        int m = 1;
    
        for (int n = 0; n < N; n++) {
            if (val >= arr[n]) {
                val -= arr[n];
            } else {
                val = k;
                val -= arr[n];
                m++;
            }
        }
    
        return m <= M;
    }
    
    int main() {
        scanf("%d %d", &N, &M);
    
        for (int n = 0; n < N; n++) {
            scanf("%d", arr + n);
    
            min = std::max(min, arr[n]);
        }
    
        while (min != max) {
            int val = min + (max - min) / 2;
            if (parametricSearch(val)) {
                max = val;
            } else {
                min = val + 1;
            }
        }
    
        printf("%d\n", max);
    
        int value = max;
        int count = 0;
        int groupCount = 0;
        for (int n = 0; n < N; n++) {
            if (value >= arr[n]) {
                value -= arr[n];
                count++;
            } else {
                value = max;
                value -= arr[n];
                result.push_back(count);
                count = 1;
                groupCount++;
            }
        }
        result.push_back(count);
    
        int i = 0;
        while (result.size() < M) {
            while (result[i] <= 1)
                i++;
    
            result[i]--;
            result.push_back(1);
        }
    
        for (int r : result)
            printf("%d ", r);
        return 0;
    }
    

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

    용돈관리 (boj 6236)  (0) 2020.06.05
    쿼드트리 (boj 1992)  (0) 2020.06.05
    별 찍기 11 (boj 2448)  (0) 2020.06.03
    트리의 높이와 너비 (boj 2250)  (0) 2020.06.03
    수학은 너무 쉬워 (boj 2904)  (0) 2020.06.03

    댓글

Designed by Tistory.