더 이상 tistory 블로그를 운영하지 않습니다. glanceyes.github.io에서 새롭게 시작합니다.

새소식

알고리즘/BOJ 풀이

BOJ 백준 22953번 도도의 음식 준비

  • -

 

BOJ 백준 22953 도도의 음식 준비

 

문제: https://www.acmicpc.net/problem/22953

 

22953번: 도도의 음식 준비

첫째 줄에 요리사의 수 N (1N10), 만들어야 할 음식의 개수 K (1K1000000), 격려해줄 수 있는 횟수 C (0C5)가 주어진다. 둘째 줄에 길이가 N인 정수 수열 A가 주어

www.acmicpc.net

 

 

K개의 요리를 조리하는 N명의 요리사의 조리시간이 주어진다. 한 요리사에게 격려를 여러 번 할 수 있고, 요리사에게 격려를 한 번 할 때마다 격려를 받은 요리사의 조리 시간은 1초 감소한다. 격려할 수 있는 최대 횟수가 C회일 때, K개의 요리를 조리하는 데 걸리는 최소 시간을 구해야 한다.

 

 

 

처음에는 Greedy(그리디) 알고리즘으로 해결하려고 했지만, 어떤 요리사에게 격려를 얼마나 하느냐에 따라 결과가 달라질 수 있어서 구현하기 어려울 것 같다고 느꼈다. 문제를 잘 관찰하면 N과 C의 값이 유난히 작은 것을 의심할 수 있는데, Brute Force(브루스 포스)를 사용하는 문제이지 않을까 하는 의심이 들었다.

 

 

 

Brute Force 방법으로 풀 수 있는지 확인하고자 시간 복잡도를 구했다. 요리사에게 격려할 수 있는 경우의수는 10의 0제곱부터 5제곱까지를 모두 더한 값이 나오는데, naive하게 10의 6승이라고 해도 백만이므로 값이 생각보다 크지 않음을 알 수 있다. 

 

 

 

K개를 요리하는 데 걸리는 최대 조리 시간은 K의 최댓값과 A의 최댓값을 곱한 값인데, 이를 고려해도 10의 12승이므로 이진 탐색을 고려하면 가능한 최소 요리 시간을 찾는데 그리 많은 시간이 걸리지 않음을 알 수 있다. log(10^12)는 약 40이므로 앞에서 구한 격려의 경우의 수 10의 6승에 40을 곱해도 주어진 제한 시간 내로 충분히 계산 가능하다.

 

 

 

즉, 격려 가능한 모든 경우마다 음식 조리를 완료할 수 있는 최소 시간을 이진 탐색으로 찾으면 가능하다. 코드를 보면 이해가 쉬울 것이다.

 

 

#include <cstdio> #include <limits.h> #include <algorithm> using namespace std; using ll = long long; const int N_MAX = 10; const ll T_MAX = (ll)1e12; int n, c; ll k, ans = T_MAX; ll a[N_MAX + 1]; void findTime(){ ll minTime = T_MAX; ll left = 1, right = T_MAX; while(left < right){ ll mid = left + (right - left) / 2; ll food = 0; for (int i = 1; i <= n; i++){ food += mid / a[i]; } if (food >= k){ minTime = mid; right = mid; } else { left = mid + 1; } } ans = min(ans, minTime); return; } void go(int cnt){ findTime(); // 격려 횟수 다 사용하면 if (cnt == c){ return; } for (int i = 1; i <= n; i++){ if (a[i] - 1 > 0){ a[i] -= 1; go(cnt + 1); a[i] += 1; } } return; } int main(){ scanf("%d %lld %d", &n, &k, &c); for (int i = 1; i <= n; i++){ scanf("%lld", &a[i]); } go(0); printf("%lld\n", ans); return 0; }

 

Contents

글 주소를 복사했습니다

부족한 글 끝까지 읽어주셔서 감사합니다.
보충할 내용이 있으면 언제든지 댓글 남겨주세요.