問題描述
工廠有 $n$ 台機器,可以用來製造產品。你的目標是製造總共 $t$ 個產品
每台機器需要的時間不同,你知道每台機器製造一個產品所需的秒數
所有機器可以同時工作,你也可以自由安排它們的工作時間表
請計算:最短需要多少時間,才能製造出 $t$ 個產品
二分搜
像這種題目:某個條件下,時間越長越容易成功(或反過來)
可以定義一個 $check(time)$ 函數,來判斷「在這個時間內是否可行」
如此我們可以不斷二分搜限縮範圍,直到找到最小的時間
二分搜的區間
常見做法有左閉右開跟左閉右閉,我在寫這題的時候就搞混這兩種
左閉右開
while (left < right) {
int mid = left + (right - left) / 2;
if (/*答案在左邊*/) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
左閉右閉
while (left <= right) {
ll mid = (left + right) / 2;
if (/*答案在左邊*/) {
ans = mid;
right = mid - 1;
} else {
left = mid + 1;
}
}
return ans;
練習題
CSES - Factory Machines
求最小製作完 $t$ 個產品的時間,答案的範圍是 [1, 最快的機器 * t]
我們只要在這個範圍二分搜即可
完整程式碼
#include <bits/stdc++.h>
using namespace std;
#define ll long long
bool solve(ll mid, ll N, ll T, int* Machine) {
ll product = 0;
for (int i = 0; i < N; i++) {
product += mid / Machine[i];
if (product >= T) return true;
}
return false;
}
ll bs(ll N, ll T, int* Machine) {
ll left = 1, right = *(min_element(Machine, Machine + N)) * T;
ll ans = INT_MAX;
while (left < right) {
ll mid = left + (right - left) / 2;
if (solve(mid, N, T, Machine)) {
right = mid;
} else {
left = mid + 1;
}
}
return left;
}
int main() {
ll n, t;
cin >> n >> t;
int machine[200005];
for (int i = 0; i < n; i++) cin >> machine[i];
cout << bs(n, t, machine) << "\n";
}