本题为二分答案,题意为从高到低依次给n个深度不同的水池和水管的流速(每个水管都一样),如果某一个池塘满了,那么
它只会向后面的的池塘溢水,问多长时间所有的池塘都能装满水和最后一个池塘什么时候装满水。
提示:如果求所以池塘什么时候装满水,那么需要每一个都装满才行;而对于最后一个什么时候装满水,
则不需要所有的都装满。
#include <iostream>
#include <stdio.h>
using namespace std;
int n,i,t;
double l,r,m,k,ans,ans2;
double a[100005];
const int maxn=1e9+7;
bool judgeAll(double m)///判断所有的,需要每一个都装满才行
{
double num=0;///标记溢出的水量
for(i=1;i <= n;i++)///此处右边界为n
{
num+=m*k;
if(num<a[i])return 0;///如果有当前时间无法装满的池塘则退出
num-=a[i];///如果之前的加上当前的水量能把当前池塘装满,此步骤为求剩余溢出的水量
}
return 1;
}
bool judgeLast(double m)///判断当前时间能否把最后一个装满
{
double num=0;
///下方i的边界不能为n,想一下如果流过倒数第二个后有溢出的水,并且流完最后一个后有剩余或者最后 一个本身自己就能装满自己,那么是不是会造成时间多算
for(i=1;i < n;i++)
{
num += (m*k);
if(num<a[i])num = 0;///如果不能装满当前池塘,则一定不会有多余的水溢到下一个池塘
else num -= a[i];///能装满,求溢到下一个池塘的水量
}
num+=(m*k);
return num > a[n];
}
int main()
{
while(scanf("%d%lf",&n,&k)!=EOF)
{
for(i=1;i<=n;i++)
{
scanf("%lf",&a[i]);
}
l=0,r=maxn;
t=70;
while(t--)///二分求时间,t为次数
{
m=(l+r)/2;
if(judgeAll(m)){ans=m;r=m;}
else l=m;
}
l=0,r=maxn;
t=70;
while(t--)
{
m=(l+r)/2;
if(judgeLast(m)){ans2=m;r=m;}
else l=m;
}
printf("%.6lf %.6lf\n",ans2,ans);///注意精确度
}
return 0;
}