AC通道:http://poj.org/problem?id=3104
Drying
Description
现在有
n
件衣服,告诉你每一件衣服上水滴的数量。
每一个时间单位中,衣服会被自然风干1滴水滴。
你也可以使用一个烤火炉(只有一个)。
在每一个时间单位中,这个烤火炉能够给一件衣服(只有一件)减少
当你使用烤火炉时,在该时间单位中,该件衣服不会被自然风干。
现在要你合理地使用烤火炉,使所有的衣服都变干的时间最短。
(每一个时间单位中,烤火炉只能烤一件衣服)
Input
第一行包括一个整数
n
,表示衣服的件数。
第二行包括用空格隔开的
第三行包括一个整数
k
,表示烤火炉的效率,即它每个时间单位能使衣服减少的水滴数。
Output
只有一个整数,表示最短的时间。
Sample Input 1
3
2 3 9
5
Sample Output 1
2
Sample Input 2
3
2 3 6
5
Sample output 2
2
HINT
对于
Solution
这道题,第一感觉是贪心。
枚举每个时间,将水滴数最大的衣服使用烤火炉。当最大水滴数为
0
的时候,就输出当前的时间。
很明显会超时:最坏情况下,最大时间将达到
所以要二分。
所以我们将最优化问题转化为了一个判定性问题。
设当前要判断的时间为
t
,对于衣服
显然,我们要判断的,就是烤火炉够不够用。
那么,若 si≤t ,那么这件衣服可以直接忽略掉,因为它不需要使用烤火炉。
若
si>t
,那么它如果自然风干,那么设它需要使用烤火炉的时间为
t0
,
那么有
t0∗k+(t−t0)≥si
⇒
t0∗(k−1)≥si−t
⇒
t0≥(si−t)/(k−1)
为了尽可能少地使用烤火炉,则
t0
取
(si−t)/(k−1)
向上取整的结果。
需要注意的是,若
k=1
,上面这个表达式就会出现错误,所以要特判。
遍历完所有的衣服,求出所有
t0
(需要使用烤火炉的衣服)之和。
若这个和大于
t
,那么
算法总复杂度为 O(nlogTmax) 。
注意需要用 long long 。
Code
#include <iostream>
#include <cstdio>
using namespace std;
long long n,la,l=1,r,ans;
long long s[100010];
inline long long Max(long long a,long long b){
return a>b?a:b;
}
bool pan(long long t){
long long ti=0;
for(long long i=1;i<=n;i++){
if(s[i]>t){
if((s[i]-t)%(la-1))
ti+=(s[i]-t)/(la-1)+1;
else ti+=(s[i]-t)/(la-1);
if(ti>t)return false;
}
}
return true;
}
int main(){
scanf("%I64d",&n);
for(long long i=1;i<=n;i++){
scanf("%I64d",&s[i]);
r=Max(r,s[i]);
}
scanf("%I64d",&la);
if(la==1){printf("%I64d\n",r);return 0;}
ans=r;
while(l<=r){
long long mid=(l+r)/2;
bool flag=pan(mid);
if(flag){
if(ans>mid)ans=mid;
if(r!=mid-1)r=mid-1;
else break;
}
else{
if(l!=mid+1)l=mid+1;
else break;
}
}
printf("%I64d\n",ans);
return 0;
}