안녕하세요! 테크지니어22입니다.
오늘은 백준 알고리즘 19700번 - 수업을 풀어보도록 하겠습니다.
https://www.acmicpc.net/problem/19700
19700번: 수업
키가 188cm, 154cm인 학생들을 한 팀으로, 키가 180cm, 161cm인 학생들을 한 팀으로, 키가 172cm인 학생을 혼자 팀으로 묶으면 총 3개의 팀을 구성할 수 있다. 더 적은 갯수의 팀으로 학생들을 묶을 수 있
www.acmicpc.net
[문제 접근]
자신보다 키 큰 사람이 ki명 이상이면 나간다는 조건 때문에 정렬이 필요하다는 생각이 들었습니다.
이 때 오름차순으로 할지 혹은 내림차순으로 할지 판단하기 위해 각각 오름차순, 내림차순 정렬하여 한 명씩 새로운 팀을 만들어 배치하는
작업을 해보았습니다. 오름차순으로 할 경우, 특정 한 명을 배정할 때 그 팀 안의 모든 사람들이 ki조건을 따져야 했고, 내림차순으로 할 경우 배정을 하려는 사람의 ki조건만 따지면 되었습니다. 그래서 내림차순으로 정렬을 했습니다.
한편, 여기에 그리디의 개념이 들어가는데 최소의 팀을 만들기 위해서는 사람을 배정할 때 인원이 가장 많은 팀에 들어가야 합니다.
인원이 가장 많은 팀에 들어가야하는 이유는, ki명이하를 만족하는 팀들 중에 가장 많은 팀에 들어가야 우리가 원하는 최소로 팀을 만들 수 있기 때문입니다.
N이 50만이하라는 것을 고려하여 set 자료구조를 생성하여 새로운 팀을 하나씩 만들고, 팀원을 조건에 맞추어 배치하였습니다.
set자료구조에는 팀의 인원을 원소로 받았습니다.
그리고 수강생을 배정할 때 자신보다 키 큰 사람이 ki명 미만(ki-1이하)인 팀을 찾아야하기 때문에, set자료구조에서 팀의 인원을 계산할 때 음수로 넣어서 사용해야합니다.
[풀이 전략]
1. 인원을 저장한 배열을 키의 내림차순으로 정렬합니다.
2. multiset 자료구조를 생성합니다.
3. 수강생 한 명씩 접근합니다.
4. multiset에 수강생의 ki-1이하가 존재하는 지 찾기 위해 + 가장 많은 팀에 들어가기 위해, lower_bound(-arr[i].second + 1)을 이용합니다.
5.만약 발견할 수 없으면 새로운 팀을 만듭니다 -> multiset에 -1을 추가합니다.
6.존재하면 그 값을 지우고 (그 값-1)을 multiset에 추가합니다.
7. multiset의 사이즈를 출력합니다.
[코드]
#include <iostream>
#include <algorithm>
#include <set>
using namespace std;
int n ;
pair<int,int> arr[500001];
int main() {
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n ;
for(int i = 0; i < n ; i++){
int h, k ;
cin >> h >> k ;
arr[i].first = h ;
arr[i].second = k ;
}
sort(arr, arr+n, greater<pair<int,int>>());
multiset<int> s;
for(int i = 0 ; i < n ; i++){
auto lower = s.lower_bound(-arr[i].second + 1) ;
if( lower == s.end()){
s.insert(-1);
} else {
// s[lower- s.begin()]--; <- 이렇게 접근 못하기 때문에 아래처럼 작성.
int v = *lower;
s.erase(lower);
s.insert(v -1);
}
}
cout << s.size();
}
[배울 점]
- set은 특성상 오름차순으로 자동 정렬됨.
- set에서도 lower_bound 사용 가능.
- set erase의 매개인자는 값뿐만 아니라 iterator도 가능.
'알고리즘 > 백준' 카테고리의 다른 글
[백준/C++] 알고리즘 2961번 - 도영이가 만든 맛있는 음식 (0) | 2024.04.24 |
---|---|
[백준/C++] 알고리즘 4991번 - 로봇 청소기 (0) | 2024.04.23 |
[백준/C++] 알고리즘 14501번 - 퇴사1 (1) | 2024.04.22 |
[백준/C++] 알고리즘 10844번 - 쉬운 계단 수 (0) | 2024.04.17 |
[백준/C++] 알고리즘 9146번 - 파도반 수열 (0) | 2024.04.17 |