poj3104
大体思路:
题意:烘干机,给出一堆衣服的水分a[i],在不加烘干机情况下自动每一分钟减少1水分,每分钟可以变改衣服(i)到烘干机中,每分钟减少k水分,求最少需要多少时间。
题解:第一时间就想到使用二分枚据答案+验证这种思路,不过这题还是有些陷阱需要注意。
1. 验证答案时,如果 a[i] <= mid,让它自然烘干即可 ; 如果a[i] > mid,那么烘干这件衣服可以分成两段时间:使用烘干机时间x1 + 自然烘干时间x2,那么可以列出等式:mid = x1 + x2; a[i] <= kx1+x2;于是得x1 >= (a[i] -mid)/(k-1);即得使用烘干机的最少时间x1
2.注意当k==1时,k-1 == 0,需要特殊处理,直接打出ans = maxV
3.注意当求left+right时,结果可能超出范围,正确的方法应该是left + (right - left)*0.5;
4.一个小技巧,整数运算中,a/b的上取整可以用(a+b-1)/b。
#include <iostream>
#include <algorithm>
using namespace std;
const int MAX_N = 100005;
int n, k;
int time[MAX_N];
bool C(int mid) {
int sum = 0;
for(int i=0; i<n; i++) {
if(time[i] > mid) {
sum += (time[i] - mid + k - 2) / (k - 1);
if(sum > mid) return true;
}
}
return false;
}
int main() {
freopen("in.txt", "r", stdin);
while(~scanf("%d", &n)) {
for(int i=0; i<n; i++) scanf("%d", &time[i]);
scanf("%d", &k);
int l = 0;
int u = *max_element(time, time+n);
if(k == 1) {
printf("%d\n", u);
continue;
}
while(l <= u) {
//防止(l+u)超出范围
int mid = l + (u - l) / 2;
if(C(mid)) {
l = mid + 1;
}
else {
u = mid - 1;
}
}
printf("%d\n", u+1);
}
fclose(stdin);
return 0;
}