POJ 3104 Drying
最让HSQ学长头疼的就是洗衣服了。洗完之后,每件衣服都有一定单位水分,在不使用烘干器的情况下,每件衣服每分钟自然流失1个单位水分,但如果使用了烘干机则每分钟流失K个单位水分。令人遗憾是HSQ所在的宿舍楼只有1台烘干机,而每台烘干机同时只能烘干1件衣服,请问要想烘干N件衣服最少需要多长时间?
输入
第一行输入N,表示有N件衣服,第二行输入N件衣服的水分ai,第三行表示烘干机每分钟烘干水分K
其中
1 ≤ N ≤ 100 000,1 ≤ ai ≤ 10^9,1 ≤ K≤ 10^9输出
输出烘干N件衣服所需要的最短时间
样例输入
3 2 3 9 5 3 2 3 6 5
样例输出
3
2
一、
看一下数据大小就知道肯定不是一个一个衣服的求时间,既然不是从衣服下手,那我们就肯定要从时间上面下手了。。。对时间二分来确定时间是多少的时候才适合
所用时间最短是1分钟,最长时间是把水份最多的衣服晒干所用的时间(不用机器)
那么之后就要对二分的时间进行判定来确定它是否符合。。
1、如果衣服上面的水分小于这个二分的时间,那他就可以不用机器,直接晒干
2、如果水分大于,那就算出来他所需要的时间
这个时候他的水分可以看作是以两种方式损失的
1、自然晒干
2、机器催干(可以说是把机器每分钟晒干的水分看成两部分)
设其x1为自然晒干的时间
x2为机器晒干的时间
则有
1、mid=x1+x2
2、v[i]<=x1+x2*(k-1)
结出来得到:x2>=(v[i]-mid)/(k-1) 即作向上取整既可以
向上取整:
假如:a/s是一个小数
为了向上取整可以写作这样(a+s)/s
那么x2>=(v[i]-mid+k-2)/(k-1)
二、
之后就要说一下二分法在不同题之间的区别
1、如果是要在一个单调序列中找一个确定的值
//https://blog.csdn.net/dijiaxing1234/article/details/81178097
public static int rank(int key,int nums[])
{
//查找范围的上下界
int low=0;
int high=nums.length-1;
//未查找到的返回值
int notFind=-1;
while(low<=high)
{
//二分中点=数组左边界+(右边界-左边界)/2
//整数类型默认取下整
int mid=low+(high-low)/2;
//中间值是如果大于key
if(nums[mid]>key)
{
//证明key在[low,mid-1]这个区间
//因为num[mid]已经判断过了所以下界要减一
high=mid-1;
}else if(nums[mid]<key)
{
//证明key在[mid+1,high]这个区间
//同样判断过mid对应的值要从mid+1往后判断
low=mid+1;
}
else
{
//查找成功
return mid;
}
}
//未成功
return notFind;
}
2、就像这一道题,是从一段范围中求出来那个值符合本题,这个值是未知的,那就用以下这种方法
#include<stdio.h>
#include<string.h>
typedef long long ll;
ll max(ll x,ll y)
{
return x>y ? x: y;
}
ll v[100005];
int main()
{
ll a,s,d,f,g;
scanf("%lld",&a);
s=0;
for(int i=1;i<=a;++i)
{
scanf("%lld",&v[i]);
s=max(s,v[i]);
}
scanf("%lld",&d);
if(d==1) printf("%lld\n",s);
else
{
f=0;
g=s;
ll mid;
while(g-f>1) //要保证他们中间有一个来隔离g和f,否则这两个数就相邻了,或者f在g的右边这个样子【f,g】就不能成立,至于f==g的时候此处值在之前就证明过不可取
{ //因为f=0不会是结果,s分出来讨论过了,所以这两个值都不会是结果,之后讨论他们的一半,如果这个mid不行,才会赋值给f或g
mid=(f+g)/2;
ll temp=0;
for(int i=1;i<=a;++i)
{
if(v[i]<=mid) continue;
ll ans=(v[i]-mid+d-2)/(d-1);
temp+=ans;
}
if(temp>mid) f=mid;
else g=mid; 因为本题求的是最短时间,那么如果有一个值满足了,不能直接跳出来,还要接着搜索看看有没有比他更短的时间,所以这里time==mid的时候不能跳出循环
}
printf("%lld\n",g);
}
return 0;
}
本人菜鸡一枚,如有错误,求指出!