Drying POJ - 3104 (二分答案)(最小值最大化)
It is very hard to wash and especially to dry clothes in winter. But Jane is a very smart girl. She is not afraid of this boring process. Jane has decided to use a radiator to make drying faster. But the radiator is small, so it can hold only one thing at a time.
Jane wants to perform drying in the minimal possible time. She asked you to write a program that will calculate the minimal time for a given set of clothes.
There are n clothes Jane has just washed. Each of them took ai water during washing. Every minute the amount of water contained in each thing decreases by one (of course, only if the thing is not completely dry yet). When amount of water contained becomes zero the cloth becomes dry and is ready to be packed.
Every minute Jane can select one thing to dry on the radiator. The radiator is very hot, so the amount of water in this thing decreases by k this minute (but not less than zero — if the thing contains less than k water, the resulting amount of water will be zero).
The task is to minimize the total time of drying by means of using the radiator effectively. The drying process ends when all the clothes are dry.
Input
The first line contains a single integer n (1 ≤ n ≤ 100 000). The second line contains ai separated by spaces (1 ≤ ai ≤ 109). The third line contains k (1 ≤ k ≤ 109).
Output
Output a single integer — the minimal possible number of minutes required to dry all clothes.
Sample Input
3 2 3 9 5 3 2 3 6 5
Sample Output
3 2
题意:每件衣服都有一定单位水分,在不使用烘干器的情况下,每件衣服每分钟自然流失1个单位水分,但如果使用了烘干机则每分钟流失K个单位水分。只有1台烘干机,而每台烘干机同时只能烘干1件衣服,请问要想烘干N件衣服最少需要多长时间?
解题思路:当看到这题我们可以发现如果你要烘干n件衣服,那么另外一半的衣服刚好能全部干是最好的,所以由此可以想到二分
代码:
#include <iostream> #include <algorithm> #include <string.h> #include <cstdio> #include <string> #include <cmath> #include <vector> #include <stack> #include <queue> #include <stack> #include <list> #include <map> #include <set> //#include <unordered_map> #define Fbo friend bool operator < (node a, node b) #define mem(a, b) memset(a, b, sizeof(a)) #define FOR(a, b, c) for(int a = b; a <= c; a++) #define RFOR(a,b, c) for(int a = b; a >= c; a--) #define sc(a) scanf("%lld",&a) #define off ios::sync_with_stdio(0) bool check1(int a) { return (a & (a - 1)) == 0 ? true : false; } using namespace std; typedef pair<int, int> pii; typedef long long ll; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; const int Maxn = 2e5 + 5; const double pi = acos(-1.0); const double eps = 1e-8; ll a[Maxn];//水分 ll n;//衣服件数 ll k;//烘干机一次烘干的水分 int solve(ll mid) { //假设目前用mid的时间烘干衣服 /*如果一件衣服a[i]小于mid,可自然风干,否则需要用机器,那么只要判断在mid时是否需要使用机器就可以 但是如果一件衣服 自然风干的时候用时t1 用机器烘干t2 (1)t1+t2 = mid (2)t1+k*t2 >= a[i] 联立两个方程解得 t2 <= mid-a[i]/(1-k) */ ll cnt = 0; FOR(i, 1, n) { if (a[i] > mid) { //如果一件衣服要使用机器 cnt += (ll)ceil((double)(a[i] - mid * 1.0) / (k - 1));//算出要烘干的次数, k==0的时候无意义 } } if (cnt <= mid) //有多余的时间 return 1; else return 0; } int main() { sc(n); FOR(i, 1, n) sc(a[i]); sc(k); sort(a + 1, a + 1 + n); if (k == 1) { //特判 printf("%lld\n", a[n]); return 0; } ll l = 1, r = a[n]; while (l <= r) {//解释一下为什么l<r : 当需要增大时间时候l = mid+1,不需要时间时候r = mid //那么当 l==r 的时候就会跳出循环输出l即可 ll mid = (l + r) >> 1; if (solve(mid)) { //如果当前用mid的时间来烘干衣服有多余的时间 r = mid - 1; } else l = mid + 1;//时间少了,需要增大时间 } printf("%lld\n", l); return 0; }