728x90
보석 상자
성공다국어
한국어
시간 제한 메모리 제한 제출 정답 맞힌 사람 정답 비율
1 초 | 128 MB | 6121 | 2193 | 1629 | 37.466% |
문제
보석 공장에서 보석 상자를 유치원에 기증했다. 각각의 보석은 M가지 서로 다른 색상 중 한 색상이다. 원장 선생님은 모든 보석을 N명의 학생들에게 나누어 주려고 한다. 이때, 보석을 받지 못하는 학생이 있어도 된다. 하지만, 학생은 항상 같은 색상의 보석만 가져간다.
한 아이가 너무 많은 보석을 가져가게 되면, 다른 아이들이 질투를 한다. 원장 선생님은 이런 질투심을 수치화하는데 성공했는데, 질투심은 가장 많은 보석을 가져간 학생이 가지고 있는 보석의 개수이다. 원장 선생님은 질투심이 최소가 되게 보석을 나누어 주려고 한다.
상자에 빨간 보석이 4개 (RRRR), 파란 보석이 7개 (BBBBBBB) 있었고, 이 보석을 5명의 아이들에게 나누어 주는 경우를 생각해보자. RR, RR, BB, BB, BBB로 보석을 나누어주면 질투심은 3이 되고, 이 값보다 작게 나누어 줄 수 없다.
상자 안의 보석 정보와 학생의 수가 주어졌을 때, 질투심이 최소가 되게 보석을 나누어주는 방법을 알아내는 프로그램을 작성하시오.
입력
첫째 줄에 아이들의 수 N과 색상의 수 M이 주어진다. (1 ≤ N ≤ 109, 1 ≤ M ≤ 300,000, M ≤ N)
다음 M개 줄에는 구간 [1, 109]에 포함되는 양의 정수가 하나씩 주어진다. K번째 줄에 주어지는 숫자는 K번 색상 보석의 개수이다.
출력
첫째 줄에 질투심의 최솟값을 출력한다.
예제 입력 1 복사
5 2
7
4
예제 출력 1 복사
3
예제 입력 2 복사
7 5
7
1
7
4
4
예제 출력 2 복사
4
문제 분석
- 질투심이 최소 = 가져가는 보석 수의 최대값이 최소가 되도록
- 최소값 구하기 -> 큰 것부터 작은 것으로 이동
- 나눌 보석 수가 커질수록 나누는 묶음의 수가 적어진다. => 묶음의 개수가 작으면 나눌 보석 수 키우기, 묶음의 개수가 크면 나눌 보석 수 줄이기
- 나눌 보석 수의 최소를 구하기때문에 묶음의 개수가 큰것부터 -> 작은것으로 이동하여 정답 구하기
- 한 학생은 같은 보석만 가질수있다고 했고, 색이 다른 보석의 개수는 서로 다르므로 DividedByZero오류 가능 => l을 1부터 시작
#include <bits/stdc++.h>
using namespace std;
int n,m, a[300004], s, ret=987654321;
int main(){
ios_base::sync_with_stdio(0); cin.tie(NULL); cout.tie(NULL);
//1. 입력받기
cin >> n >> m; //아이들 수, 보석 수
for(int i=0;i<m;i++){
cin >> a[i];
s = max(s, a[i]); //최대 보석 개수
}
//2. 이분탐색 수행하기
int l=1; int r=s; //ㅣ---r
int mid=0;
while(l<=r){
mid=(l+r)/2; //나눌 보석 수 크면 묶음수는 적다.
int cnt=0;
for(int i=0;i<m;i++){
cnt += a[i]/mid;
if(a[i]%mid) cnt++;
}
if(cnt<=n){ //묶음이 더 적으면(mid가 크다.)
r=mid-1; //보석 수 줄이기
ret=min(mid, ret); //최소값 구하기
} //묶음이 더 크면
else l=mid+1;;
}
//3. 정답 출력
cout << ret <<"\n";
}
어려웠다..
728x90
'알고리즘 > 알고리즘 문제풀이' 카테고리의 다른 글
17829번: 222-풀링 (0) | 2023.03.10 |
---|---|
11772번: 가장 긴 감소하는 부분 수열 (0) | 2023.03.10 |
17951번: 흩날리는 시험지 속에서 내 평점이 느껴진거야 (0) | 2023.03.09 |
6주차: 이분탐색과 LIS (0) | 2023.03.08 |
1931번: 회의실 배정 (0) | 2023.03.07 |