题目链接:POJ - 3104
题意:
给出一组数据,每个数字代表每件衣服的含水量,现在想要让衣服变干,有两种方法,第一种是自然风干,一分钟蒸发一单位的水,第二种是用烘干机烘干,一分钟蒸发k单位的水,问烘干所有衣服的最短时间
题解:
时间限制是2s,数据范围是1e9,那么这道题不能直接用暴力的方法,不然会超时的!
优化:二分
这道题大致可以分为两个部分
1、自然风干时间
2、烘干机烘干的时间
那么一定存在一个值m,使得烘干的水量为(m-c)+c*k的和最小。其中m为烘干衣服所用的时间,c为自然风干的时间。
也就是说现在要求的是 a[i]=(m-c)+c*k -> c=(a[i]-m)*1.0/(k-1);
不过这里要注意小细节,可以参见文章:https://blog.csdn.net/zbq_tt5/article/details/88950069。
也就是每件衣服的烘干时间,每件衣服的烘干时间加起来后的最小值
不过要注意的是,如果说k==1的话,分母就位0了,所以k=1的情况要特判断!
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
int N,a[100005],k,max_number;
int main()
{
while(~scanf("%d",&N))
{
for(int i=0; i<N; ++i)
{
scanf("%d",&a[i]);
if(a[i]>max_number)
max_number=a[i];
}
//找到最大的衣服的单位水分,方便后来计算k==1的情况
cin>>k;
if(k==1)
{
cout<<max_number<<endl;
continue;
}
int left=1,right=max_number,mid;
ll num_puts;
while(left<=right)
{
mid=(left+right)/2;
ll number=0;
for(int i=0;i<N;++i)
{
if(a[i]>mid)
{
number+=(ceil((a[i]-mid)*1.0/(k-1)));
}
}
if(number<=mid)
{
num_puts=mid;
right=mid-1;
}
else
left=mid+1;
}
printf("%d\n",num_puts);
}
return 0;
}