https://www.acmicpc.net/problem/1654
1. 문제 이해
저 같은 경우는 문제 이해에서 완벽하게 넘어가지 않아 꽤나 고생했던 문제입니다.
함정 point는 n개의 똑같은 랜선을 만들어야 하는데 n보다 큰 경우인 n+1, n+2 경우에도 최대값을 체크해 줘야 한다는 것 입니다.
2. 접근방법
두가지 부분에서 조심해야 합니다.
첫 번째, 시간초과에 주의해야 합니다.
완전탐색을 할 경우, 시간이 초과하기 때문에 binary search를 사용해야 합니다.
두 번째, 범위초과에 주의해야 합니다.
int 형으로 선언할 경우, 범위가 초과하는 경우(예를 들어, left(2^31-1 / 2)+right(2^31) / 2 = mid(int형 초과), 잘린 갯수(1로 잘랐을대 int형 초과))가 발생할 수 있기 때문에 long long형을 사용하도록 합니다.
세 번째,
저 같은 경우는 속도를 올리기 위해서
'가장 작은 값을 기준으로 0부터 가장 작은 값 까지 이분탐색을 하자!' 로 접근하였습니다.
하지만 이렇게 접근한 경우, 밑의 test case 에서는 0이 출력 되버립니다. 즉, 완전 탐색이 할 필요가 있다는 것입니다.
4 5
100
200
302
400
그래서 최대값을 찾아 접근하여야 합니다. 최대값으로 설정할경우에도 이분탐색으로 탐색하기 때문에 O(logN) 이 되므로 시간 초과에 대해서 걱정 하지 않아도 됩니다.
3. 문제 해결
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 32 33 34 35 36 37 38 39 40 41 42 43 | #include <cstdio> #define MAX_SIZE 10005 using namespace std; int k, n; long long res; int arr[MAX_SIZE]; long long calc_lens(long long len) { long long output = 0; for (int i = 0; i < k; i++) { output += (arr[i] / len); } return output; } int main() { scanf("%d %d", &k, &n); long long _max = 0; for (int i = 0; i < k; i++) { scanf("%d", &arr[i]); _max = _max < arr[i] ? arr[i] : _max; } long long l = 1, r = _max; while (l <= r) { long long mid = (l + r) / 2; long long tmp = calc_lens(mid); if (tmp < n) { // 크게 잘른것, 자르는 크기 줄여주기 r = mid - 1; } else { // 크거나 같은경우 res = res < mid ? mid : res; l = mid + 1; } } printf("%lld\n", res); return 0; } | cs |
※ long long 형은 9byte로 int(4byte)보다 더 많은 수를 표현할 수 있다.
※ MAX_SIZE 실수를 자꾸 한다.... 시간 초과가 날 경우 용량을 잘 확인하자!!!
'Algorithm > solution' 카테고리의 다른 글
#10815. 숫자카드 (0) | 2017.12.24 |
---|---|
#1065. 한수 (0) | 2017.12.24 |
#11866. 조세퍼스 문제 (0) | 2017.12.01 |
#10828. 스택 (0) | 2017.11.29 |
#1874. 스택수열 (1) | 2017.11.29 |