[백준 17179번 C/C++] 케이크 자르기

 

https://www.acmicpc.net/problem/17179

 

17179번: 케이크 자르기

첫 번째 줄에 자르는 횟수가 담긴 목록의 길이 N과 자를 수 있는 지점의 개수 M, 그리고 롤 케이크의 길이인 정수 L이 주어진다. (1 ≤ N ≤ M ≤ 1,000, 1 < L ≤ 4,000,000) 다음 M줄에 걸쳐 자를 수 있는

www.acmicpc.net


 

 

해결전략

 

이분탐색, 매개변수 탐색

 


 

 

 

 

 

 


 

 

 

코드

 

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

// n: 자르는 횟수, m: 자를 수 있는 위치 개수, l: 롤 케이크의 길이를 저장
int n, m, l;
// v: 자르는 위치를 저장할 벡터
vector<int> v;

// 목표한 크기의 조각으로 롤 케이크를 자를 수 있는지 판별
bool isValid(int givenCnt, int piecelength)
{
    int cnt = 0; // 롤 케이크를 자른 횟수
    int cuttingLocation = 0; // 자른 롤 케이크의 위치

    // 자를 수 있는 위치를 순회하면서, 목표 횟수에 도달할 때까지 자른다
    for(int i = 0; i < m && cnt < givenCnt; i++)
    {
        if (v[i] - cuttingLocation >= piecelength)
        {
            cnt++;
            cuttingLocation = v[i];
        }
    }

    // 목표 횟수로 자르고 남은 롤 케이크도 목표하는 크기이면 true를 반환
    if (cnt == givenCnt && l - cuttingLocation >= piecelength)
        return true;

    return false;
}

int Cut(int givenCnt, int length)
{
    //이분탐색 초기값
    int left = 1; // 최소 케이크 조각 길이
    int right = length; // 최대 케이크 조각 길이

    int result = 0; // givenCnt 회 자른 경우 가장 작은 조각 길이의 최댓값
    int mid;

    while (left <= right)
    {
        mid = (left + right) / 2;

        if(isValid(givenCnt, mid))
        {
            result = mid; // 가장 작은 조각의 최대 길이를 업데이트
            left = mid + 1;
        }
        else 
        {
            right = mid - 1;
        }
    }

    return result;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);

    cin >> n >> m >> l;

    v.resize(m);
    for(int i = 0; i < m; i++){
        cin >> v[i];
    }

    // 자르는 위치를 정렬. 해당문제는 굳이 정렬하지 않아도 된다.
    sort(v.begin(), v.end());

    for(int i = 0; i < n; i++){
        int givenCnt;
        cin >> givenCnt;

        cout << Cut(givenCnt, l) << "\n";
    }

    return 0;
}