题目描述
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数 N 和 F ,数据间用空格隔开。
接下来 N 行,每行输出一个整数,第i+1行输出的整数代表,第i片区域内包含的牛的数目。
输出格式
输出一个整数,表示围起区域内每块地包含的牛的数量的平均值可能的最大值乘以1000得到的数值。
数据范围
1≤N≤100000
1≤F≤N
样例
输入样例:
10 6
6
4
2
10
3
8
5
9
4
1
输出样例:
6500
算法
(实数域二分)
实数域二分就是将牛数量的最大和最小去二分,将中间数mid假设为当前的牛的平均数
find(double avg)中:
传入的参数 avg 表示的是假设答案是 avg
f[i]记录的是第一个区域到第i个区域中 牛的平均数-avg 的结果
遍历过程中 ,j从0 开始,要是存在f[j][HTML_REMOVED]=maxx,因为f[j]<=maxx<=0,所以证明从j+1-i 区域中牛的平均数比avg 还要大
这道题实数域的二分,就是用find(mid)函数去求是否存在区间比mid还大,运用二分的思想,求解平均数
C++ 代码
#include<iostream>
using namespace std;
int cow[100100];
double f[100100];
int N,M;
bool find(double avg)//
{
for(int i=1;i<=N;i++){
f[i]=f[i-1]+cow[i]-avg;//f[i]表示从1-i地区牛的平均数减去avg
}
double maxx=0.0;
for(int i=M,j=0;i<=N;i++,j++){
maxx=min(maxx,f[j]); //如果在0-j个地区(即左侧第一个地区)牛平均数没有达到0,记录下来
if(maxx<=f[i]){ //如果0-i个地区(最右边)牛的平均数比记录的最小平均数还大
return true; //证明,从j+1-i地区的牛的平均数>=avg,返回true
}
}
return false;
}
int main()
{
ios::sync_with_stdio(false);
cin>>N>>M;
double l=1,r=2000;
for(int i=1;i<=N;i++){
cin>>cow[i];
}
double mid;
while(r-l>1e-5){ //将l和r的范围缩小的规定的范围内
mid=(l+r)/2;
if(find(mid)){ //find()函数返回true,表示有区间的牛的平均数比mid还要大
l=mid;
}
else{
r=mid;
}
}
cout<<int(r*1000)<<endl;
return 0;
}