题意:
给定n个池塘,往里面注水,给定单位时间的注水量。
注:1、这n个池塘是同时注水的,也就是说任一时间内,每个池塘注入的水量是相同的。
2、这n个池塘所在高度是逐渐递减的,如果第i个池塘满了后继续注水,水将会往第i+1个池塘流,依次类推。
求①最后一个池塘刚好满的时间;②所有池塘刚好满的时间。
题解:
一、二分时间,检验答案
二、直接贪心
一、二分时间,检验答案(详解见代码)
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; const double INF=1e9+10; ll a[maxn]; ll n,f; bool judge1(double t) { double sum=0;//记录所有池塘的溢出量 for(int i=0;i<n-1;i++) { sum+=t*f;//每次往里面注入 t*f 单位的水 if(sum<a[i])//和第i池塘的容量作比较 sum=0;//如果小于a[i] 则sum里的水全部进入第i个池塘里面 else sum-=a[i];//否则sum里的水变为 sum-a[i] } sum+=t*f; if(sum>=a[n-1])//循环结束后 如果sum里的水大于等于最后一个的容量,则说明t时间内最后一个池塘会注满 return true; else return false; } bool judge2(double t) { double sum=0;//记录所有池塘的溢出量 for(int i=0;i<n;i++) { sum+=t*f;//每次往里面注入 t*f 单位的水 if(sum<a[i])//和第i池塘的容量作比较,如果sum里的水小于第i个池塘的容量,则说明有池塘不满,直接返回false return false; sum-=a[i];//否则sum里的水变为 sum-a[i] } return true; } int main() { int K=100;//(100次二分,精确答案) while(scanf("%lld%lld",&n,&f)!=EOF) { ll MAX=0; memset(a,0,sizeof(a)); for(int i=0;i<n;i++) { scanf("%lld",&a[i]); } // 1. double l=0,r=INF; double t1,t2; K=100; while(K--) { double mid=(l+r)/2; if(judge1(mid)) { r=mid; } else { l=mid; } } t1=r; // 2. K=100; l=0,r=INF; while(K--) { double mid=(l+r)/2; if(judge2(mid)) { r=mid; } else { l=mid; } } t2=r; printf("%.6lf %.6lf\n",t1,t2); } return 0; }
二、直接贪心
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=1e5+10; const double INF=1e9+10; ll a[maxn]; int main() { ll n,f; while(scanf("%lld%lld",&n,&f)!=EOF) { memset(a,0,sizeof(a)); for(int i=0;i<n;i++) { scanf("%lld",&a[i]); } // 1. double su1=0,sum1=0,t1=INF; for(int i=n-1;i>=0;i--) //从最后一个池塘开始 { sum1+=a[i]; su1+=f; t1=min(t1,sum1*1.0/su1);//求最后m个所有时间的平均值 } // 2. double su2=0,sum2=0,t2=0; for(int i=0;i<n;i++) { sum2+=a[i]; su2+=f; t2=max(t2,sum2*1.0/su2); } printf("%.6lf %.6lf\n",t1,t2); } return 0; }