USACO 2003 March Green - Best Cow Fences
题目
Farmer John's farm consists of a long row of N (1 <= N <= 100,000)fields. Each field contains a certain number of cows, 1 <= ncows <= 2000.
FJ wants to build a fence around a contiguous group of these fields in order to maximize the average number of cows per field within that block. The block must contain at least F (1 <= F <= N) fields, where F given as input.
Calculate the fence placement that maximizes the average, given the constraint.
翻译
农夫约翰的农场由 N 块田地组成,每块地里都有一定数量的牛,其数量不会少于 1 头,也不会超过 2000 头。
约翰希望用围栏将一部分连续的田地围起来,并使得围起来的区域内每块地包含的牛的数量的平均值达到最大。
围起区域内至少需要包含 F 块地,其中 F 会在输入中给出。
在给定条件下,计算围起区域内每块地包含的牛的数量的平均值可能的最大值是多少。
题解
首先数学化题目。他是想说:
对于一个数列
从数据范围可知复杂度应当低于
我们跳过比值定义式,从平均数的“移多补少”原理思考:我们把每个元素减去平均数,结果就删去了问题中的“平均数”字符串,发现现在要判断的问题变为:是否存在一个子段和非负。子段和……好解决啊!只需要考虑最大子段和即可,用双指针解决。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath> //poj 不支持万能头……
using namespace std;
int n,f,c[100005];
double s[100005],l,r,mid;
bool check(double ave){
double mn=0; //mn 记录了最小前缀和…未必是第一个(有负数)!
for(int i=1;i<=n;i++)s[i]=s[i-1]+c[i]-ave;
for(int i=0,j=f;j<=n;i++,j++){ //双指针优化
mn=min(mn,s[i]);
if(s[j]-mn>=0)return true;
}return false;
}
signed main(){
scanf("%d%d",&n,&f);
for(int i=1;i<=n;i++)scanf("%d",c+i),r=max(r,1.0*c[i]);
while(r-l>1e-5){
mid=(l+r)/2;
if(check(mid))l=mid;
else r=mid;
}printf("%d\n",int(r*1000));
return 0;
}
思维方式
解决不了的问题转化成了可解决的!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律