最佳牛围栏
题目
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于1头,也不会超过2000头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
输入格式
第一行输入整数 N 和 F ,数据间用空格隔开。
接下来 N 行,每行输出一个整数,第i+1行输出的整数代表,第i片区域内包含的牛的数目。
输出格式
输出一个整数,表示平均值的最大值乘以1000再 向下取整 之后得到的结果。
数据范围
数据范围
1 ≤ N ≤ 100000 1 ≤ F ≤ N 1≤N≤100000 \\ 1≤F≤N 1≤N≤1000001≤F≤N
输入样例
10 6
6
4
2
10
3
8
5
9
4
1
输出样例
6500
题解一(TLE)
思路
- 前缀和暴力枚举
- 会出现TLE报错
#include <iostream>
using namespace std;
const int N = 1e5 + 20;
double a[N], s[N];
int n, m;
int main () {
cin >> n >> m;
for (int i = 1; i <= n; i ++) cin >> a[i];
for (int i = 1; i <= n; i ++) s[i] = s[i-1] + a[i];
double res = 0;
for (int i = m; i <= n; i ++)
for (int j = 0; j <= i - m; j ++)
res = max(res, (s[i] - s[j]) / (i - j));
cout << int(res * 1000);
return 0;
}
题解二
思路
- 浮点数二分法
- check(avg) 函数目的:判断是否存在一段连续序列使其平均值大于avg
#include <iostream>
using namespace std;
const int N = 1e5 + 20;
double a[N], s[N];
int n, m;
bool check(double avg) {
for (int i = 1; i <= n; i ++) s[i] = s[i-1] + a[i] - avg;
double minv = 0;
for (int i = 0, j = m; j <= n; i ++, j ++) {
minv = min(minv, s[i]);
if (s[j] - minv >= 0) return true;
}
return false;
}
int main () {
cin >> n >> m;
double l = 0, r = 0;
for (int i = 1; i <= n; i ++) {
cin >> a[i];
r = max(r, a[i]);
}
while (r - l > 1e-5) {
double mid = (l + r) / 2;
if (check(mid)) l = mid;
else r = mid;
}
cout << int(r * 1000);
return 0;
}
参考链接
- https://www.acwing.com/solution/acwing/content/1148/