반응형
rolypolytoy
현's story
rolypolytoy
전체 방문자
오늘
어제
  • 분류 전체보기
    • 현's tory
      • 여행
      • 개인사업
      • 컨프런스
      • 채용지원
    • Vision AI | 3D Graphics
      • Vision AI
      • OpenGL
    • 프로그래밍 언어
      • C++
      • Python
    • Computer Science
      • 운영체제
    • 알고리즘
      • 백준
      • 프로그래머스
      • 개념정리
    • 유용한 링크
      • 개발

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • vscodeopengl
  • IOS
  • iOSMetal
  • 알고리즘구현
  • 백준2533
  • 백준13397
  • PlantUML
  • 디자인패턴
  • 백준다이나믹
  • 백준2169
  • 프로그래머스실패율
  • 백준1756
  • 백준문제풀이
  • 백준이분탐색
  • EffectiveC++
  • 백준2302
  • 백준
  • 백준알고리즘
  • iOS비동기
  • 사회망서비스
  • openglvscode
  • DFS조합
  • sync
  • 백준17471
  • 알고리즘
  • 상표특허출원
  • 백준사회망서비스
  • c++
  • 아키텍처패턴
  • 다이나믹프로그래밍

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
rolypolytoy
알고리즘/백준

[백준 13397] 구간 나누기 2 C++

[백준 13397] 구간 나누기 2 C++
알고리즘/백준

[백준 13397] 구간 나누기 2 C++

2021. 3. 15. 15:41
반응형

www.acmicpc.net/problem/13397

 

13397번: 구간 나누기 2

첫째 줄에 배열의 크기 N과 M이 주어진다. (1 ≤ N ≤ 5,000, 1 ≤ M ≤ N) 둘째 줄에 배열에 들어있는 수가 순서대로 주어진다. 배열에 들어있는 수는 1보다 크거나 같고, 10,000보다 작거나 같은 자연수

www.acmicpc.net

 

m개 이하의 구간을 나누어서 각 구간마다의 최댓값 최솟값을 뺀 값 중에서,

최댓값이 나올 수 있는 모든 경우의 수에서

최댓값 중에서 최솟값을 구하는 문제입니다.

구해야하는 값이 조금 복잡하다고 느낄 수 있습니다. 각 구간마다의 최댓값 최소값을 뺀 값 중에서 최댓값을 구하는건 알겠지만,

그러한 구간의 경우수가 정말 많기 때문에, 각 경우의 수마다의 최댓값 중에서 최솟값을 구하는 문제입니다.

 

구간의 경우의 수를 나누어야하는데, 브루트 포스로 나누려고 생각했을 때

예외처리 하기가 복잡해지고 경우의 입력 n에 따라서 기하급수적으로 많아 질것이라고 생각했습니다.

 

따라서, 이분탐색을 이용해서 목표하고자하는 최종 값인 최댓값중의 최솟값을 mid 파라미터로 설정하면서,

mid에 따라서, mid보다 큰 최댓값을 가지는 구간들을 카운트해서 m 개수 보다 작을 때 mid의 최솟값을 구하면 됩니다. 

 

코드로 나누어서 설명을 하자면,

for (int i = 0; i < n; i++) cin >> arr[i]; // 입력

    int right = *max_element(arr.begin(), arr.end()); // 입력받은 배열 중 최댓값을 right값으로 설정
    int left = 0; // 최솟값 0
    int res = right;

    while(left <= right){ // 적절한 값을 찾기 위해서 이분탐색으로 하나씩 돌려본다.
        int mid = (left + right) / 2;

        if (cal(arr, mid)){
            if (res > mid) res = mid; // 최솟값 업데이트해주기 // cal함수를 통해서 조건에 맞는 m개 이하의 구간을 찾았을 때, mid의 최솟값을 업데이트해준다.
            right = mid - 1; // mid를 더 작게 만들어보기
        } else left = mid + 1; // mid를 더 크게 만들어보기
    }

입력을 받은 뒤,

left(최솟값)은 0, right(최댓값)은 배열 중에서 가장 큰 원소를 대입합니다.

 

이분탐색을 통해서 (left + right) / 2인 mid (구간 경우의 수 (최댓값-최솟값)의 최댓값 중에서 최솟값 = 목표하는 값)을 설정한 뒤,

그 값보다 이상인 값을 찾으면 됩니다.(해당 구간을 임의로 나누어서 m개 이하로 만들면 됩니다_)

 

m개 이하의 mid이상이 만족되는 구간을 찾는 코드는

bool cal(vector<int> &arr, int mid){
    vector<int> temp;

    int cnt = 1;
    int minV, maxV;

    minV = arr[0];
    maxV = arr[0];

    for (int i = 1; i < n; i++){
        
        if (arr[i] < minV) minV = arr[i];
        if (arr[i] > maxV) maxV = arr[i];

        if ((maxV - minV) > mid){ // 차이가 목표하는 mid보다 크면 구간 카운트 + 1
            cnt++;
            minV = arr[i];
            maxV = arr[i];
        }
    }
    return cnt <= m;
}

입니다.

 

전체 코드

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

int n, m;

bool cal(vector<int> &arr, int mid){
    vector<int> temp;

    int cnt = 1;
    int minV, maxV;

    minV = arr[0];
    maxV = arr[0];

    for (int i = 1; i < n; i++){
        
        if (arr[i] < minV) minV = arr[i];
        if (arr[i] > maxV) maxV = arr[i];

        if ((maxV - minV) > mid){
            cnt++;
            minV = arr[i];
            maxV = arr[i];
        }
    }
    return cnt <= m;
}
void solution(){

    cin >> n >> m;
    vector<int> arr(n);

    for (int i = 0; i < n; i++) cin >> arr[i];

    int right = *max_element(arr.begin(), arr.end());
    int left = 0;
    int res = right;

    while(left <= right){ // 적절한 값을 찾기 위해서 이분탐색으로 하나씩 돌려본다.
        int mid = (left + right) / 2;

        if (cal(arr, mid)){
            if (res > mid) res = mid; // 최솟값 업데이트해주기
            right = mid - 1;
        } else left = mid + 1;
    }


    cout << res << '\n';    

}
int main(){

    ios_base::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    solution();

    return 0;
}

반응형
저작자표시 비영리 변경금지 (새창열림)

'알고리즘 > 백준' 카테고리의 다른 글

[백준 1756] 피자 굽기 C++  (0) 2021.03.02
[백준 2302] 극장 좌석 C++  (0) 2021.01.26
[백준 2533] 사회망 서비스(SNS) C++  (0) 2021.01.26
[백준 17471] 게리맨더링 C++  (0) 2021.01.22
[백준 2169] 로봇 조종하기 C++  (0) 2021.01.22
    '알고리즘/백준' 카테고리의 다른 글
    • [백준 1756] 피자 굽기 C++
    • [백준 2302] 극장 좌석 C++
    • [백준 2533] 사회망 서비스(SNS) C++
    • [백준 17471] 게리맨더링 C++
    rolypolytoy
    rolypolytoy

    티스토리툴바

    단축키

    내 블로그

    내 블로그 - 관리자 홈 전환
    Q
    Q
    새 글 쓰기
    W
    W

    블로그 게시글

    글 수정 (권한 있는 경우)
    E
    E
    댓글 영역으로 이동
    C
    C

    모든 영역

    이 페이지의 URL 복사
    S
    S
    맨 위로 이동
    T
    T
    티스토리 홈 이동
    H
    H
    단축키 안내
    Shift + /
    ⇧ + /

    * 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.