일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 백준 랜선 자르기
- kotlin retrofit
- 백준 4949
- 안드로이드 공공데이터
- ViewBinding Fragment
- 백준 11866
- kotlin fragment
- 좌표 정렬하기2
- 안드로이드 미세먼지
- 백준 1837
- 공공데이터 kotlin
- 백준 요세푸스 문제0
- 공공데이터 retrofit
- 인트로 애니메이션
- 백준 암호제작
- 백준 1920
- 코틀린 공공데이터
- 백준
- 안드로이드 인트로 코틀린
- 안드로이드 인트로 화면
- 백준 통계
- 백준 11650
- 좌표 정렬하기
- 모각코
- 백준 11651
- 수 정렬하기3
- 코틀린 미세먼지
- 나이순 정렬
- 백준 균형잡힌 세상
- Fragment 이동
- Today
- Total
개발 지식 공유, 복습
백준 - 1654(랜선 자르기) C++ 본문
https://www.acmicpc.net/problem/1654
이번 문제는 k개의 랜선을 잘라서 모두 길이가 같은 n개의 랜선으로 만들어야 하는데 이때의 최대 길이를 구하는 문제이다. (n보다 많이 만드는 것도 n개를 만드는 것에 포함된다.)
이 문제의 접근 방법은 랜선의 길이를 1부터 가장 긴 랜선의 길이만큼 브루트 포스를 이용해서 구할 수도 있겠지만, 문제를 보면 한 랜선의 최대길이는 2^31 - 1 이하이므로 엄청나게 커 시간 초과가 일어날 것이다.
그래서 이분 탐색을 이용해 접근해 보고자 한다.
여기서 low는 1로, high는 k개 랜선 중 가장 길이가 큰 것을 high로 잡는다.
이때 랜선의 길이는 int형의 maximum이므로 low, high의 자료형을 long long으로 해주었다. (mid를 계산할 때 둘을 더하고 2로 나누거나 while 형 조건을 확인할 때 low가 high보다 커질 수 있으므로)
이분 탐색 부분 코드이다.
while (low <= high)
{
int cnt = 0;
long long mid = (low + high) / 2;
for (int i = 0; i < k; i++)
{
cnt += arr[i] / mid;
}
// 전선 길이 up
if(cnt >= n){
if(answer < mid)
answer = mid;
low = mid + 1;
}
// 전선 길이 down
else
high = mid - 1;
}
while문 안에서 초기의 각 랜선의 길이에 접근해 mid로 나눈 몫을 더해준다. (한 기존 랜선당 mid로 나눴을 때 만들어질 수 있는 랜선의 개수)
그 합이 n 이상이라면(문제에서 n보다 많이 만드는 것도 n개를 만드는 것에 포함된다고 하니...), mid가 기존 답보다 클 경우를 확인해 그 mid가 n개로 나눈 랜선의 최대길이로 업데이트한다.
그리고 더 큰 길이로 랜선을 나누는 것을 시도하기 위해 low = mid + 1로 업데이트한다. (우린 n개 이상으로 나눌 수 있는 최대 랜선의 길이를 구해야 하므로 자를 랜선의 길이를 늘려야 한다.)
n보다 작다면, 더 작은 길이로 랜선을 나눠야 하므로 high = mid - 1로 업데이트하며 이를 반복한다. (최대 n개 이상은 만들어야 하므로 자를 랜선의 길이를 줄여야 한다.)
전체 코드이다.
#include <bits/stdc++.h>
using namespace std;
int main(){
int k, n;
cin >> k >> n;
int arr[k];
// 각 랜선들의 길이를 저장
for (int i = 0; i < k; i++)
cin >> arr[i];
long long high = *max_element(arr, arr + k);
long long low = 1;
int answer = INT_MIN;
while (low <= high)
{
int cnt = 0;
long long mid = (low + high) / 2;
for (int i = 0; i < k; i++)
{
cnt += arr[i] / mid;
}
// 전선 길이 up
if(cnt >= n){
if(answer < mid)
answer = mid;
low = mid + 1;
}
// 전선 길이 down
else
high = mid - 1;
}
cout << answer << "\n";
return 0;
}
'알고리즘(백준)' 카테고리의 다른 글
백준 - 1837(암호제작) C++ (0) | 2022.01.14 |
---|---|
백준 - 11866(요세푸스 문제0) C++ (0) | 2021.12.26 |
백준 - 4949(균형잡힌 세상) C++ (0) | 2021.12.25 |
백준 - 2108(통계학) C++ (0) | 2021.12.21 |
백준- 1920(수 찾기) C++ (0) | 2021.09.01 |