일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 장고
- java
- django rest framework
- javascript
- AWS
- 알고리즘 문제
- PYTHON
- Git
- es6
- django ORM
- MAC
- 파이썬 알고리즘
- API
- 알고리즘 풀이
- react
- Algorithm
- form
- CSS
- 알고리즘 연습
- c++
- Baekjoon
- 파이썬
- web
- DRF
- HTML
- Django
- 알고리즘
- django widget
- 백준
- js
- Today
- Total
수학과의 좌충우돌 프로그래밍
[C++] BAEKJOON 1654 랜선 자르기 본문
https://www.acmicpc.net/problem/1654
1654번: 랜선 자르기
첫째 줄에는 오영식이 이미 가지고 있는 랜선의 개수 K, 그리고 필요한 랜선의 개수 N이 입력된다. K는 1이상 10,000이하의 정수이고, N은 1이상 1,000,000이하의 정수이다. 그리고 항상 K ≦ N 이다. 그 후 K줄에 걸쳐 이미 가지고 있는 각 랜선의 길이가 센티미터 단위의 정수로 입력된다. 랜선의 길이는 231-1보다 작거나 같은 자연수이다.
www.acmicpc.net
이분탐색
을 이용하여 문제를 해결하였습니다.
이분탐색을 사용하지 않을 시
이분탐색을 사용하지 않은 오답부터 확인해보겠습니다.
자를 랜선의 길이가 1 일 때 부터 보유하고 있는 랜선 중 최대 길이가 될 때 까지 하나씩 확인하여 개수가 N 개 이상이 되는 경우를 찾아줍니다. 이 경우, 시간복잡도를 살펴보면 랜선의 길이가 1부터 최대 랜선의 길이까지 순회하므로 O(2^31)
, 보유하고 있는 랜선의 개수만큼 순회하며 총 몇 개가 만들어지는지 확인하므로 O(K)
(1<=k<=10,000) 이므로 시간초과 가 발생합니다.
#include <iostream>
using namespace std;
int lan[100000];
int main(int argc, const char * argv[]) {
int K,N;
cin >> K >> N;
int maxlan = 0;
for (int i=0;i<K;i++){
cin >> lan[i];
if (lan[i] > maxlan)
maxlan = lan[i];
}
int maxLength = 0;
for (int length=1;length<maxlan;length++){
int count = 0;
for (int i=0;i<K;i++){
count += lan[i] / length;
if (count >= N) break;
}
if (count >= N){
maxLength = max(maxLength, length);
}
}
cout << maxLength << "\n";
return 0;
}
이분탐색을 사용할 시
따라서 이분탐색을 이용하여 시간을 줄일 수 있습니다.
자를 랜선의 길이를 1부터 보유하는 최대 랜선의 길이까지 전부 확인하지 않고 이분탐색을 이용해 확인하게 됩니다. 해당하는 랜선의 길이로 잘랐을 때 N 개보다 더 나왔다면, 길이를 증가시키고, N개보다 적게 나왔다면 길이를 감소시켜가며 탐색을 하게 됩니다.
자료형을 신경쓰지 못해서 틀렸는데, 각 랜선의 길이는 2^31-1 이하의 수로 int 자료형으로 표현할 수 있지만,
long long mid=(right+left)/2;
이분 탐색을 수행하기 위해 중간 지점을 찾는 과정에서 두 수를 더하는 순간, 범위를 벗어나는 경우가 생깁니다. 따라서 long long 으로 선언해줘야 합니다.
#include <iostream>
using namespace std;
int lan[10000];
int main(int argc, const char * argv[]) {
int K,N;
cin >> K >> N;
long long maxlan = 0LL;
for (int i=0;i<K;i++){
cin >> lan[i];
if (lan[i] > maxlan)
maxlan = lan[i];
}
long long left = 1LL;
long long right = maxlan;
int answer = 0;
while (left<=right){
long long mid=(right+left)/2;
long long count = 0LL;
for (int i=0;i<K;i++){
count += lan[i] / mid;
}
if (count >= N){
answer = mid;
left = mid+1;
}
else {
right = mid-1;
}
}
cout << answer << "\n";
return 0;
}
'알고리즘 > C++' 카테고리의 다른 글
[C++] BAEKJOON 2110 공유기 설치 (0) | 2019.09.21 |
---|---|
[C++] BAEKJOON 2805 나무 자르기 (0) | 2019.09.21 |
[C++] BAEKJOON 1074 Z (0) | 2019.09.20 |
[C++] BAEKJOON 2447 별찍기 - 10 (0) | 2019.09.19 |
[C++] BAEKJOON 1992 퀴드트리 (0) | 2019.09.19 |