usaco 2003 月赛 Best Cow Fences & poj2018 题解
来源:互联网 发布:淘宝订购服务怎么取消 编辑:程序博客网 时间:2024/05/01 23:04
转载请注明:http://blog.csdn.net/jiangshibiao/article/details/21963437
【原题】
Description
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.
Input
* Lines 2..N+1: Each line contains a single integer, the number of cows in a field. Line 2 gives the number of cows in field 1,line 3 gives the number in field 2, and so on.
Output
Sample Input
10 66 4210385941
Sample Output
6500
Source
【大意】给出N头牛,每头牛有一个权值。你要选连续的一些牛,而且数量至少是F。求选出的牛的权值最大平均数。输出ans*1000后截尾取整。
【序言】做了这道题,真的是感触良多。
【初步分析】很容易想到是二分来验证答案,而验证过程不易思考。受分数规划的影响,我们可以每次把ai减去二分出来的ans,变成bi数组。如果在b中找到一段长度大于等于F且总和大于等于0的情况,就是可行的。
【再想】因为是“大于等于F”,所以不能用单调队列来做。
我们先考虑“等于F”的情况。自然,这很容易,直接一个for即可。但是有可能我们在某个等于F的情况时,还要向左或向右拓展。为了叙述方便,我们先定为向左拓展。到底要不要拓展取决于左侧是否有大于0的一段。那么思路就来了:我们先用sum[i]表示b中从1到i的总和。等于F的情况时:sum[i+f-1]-sum[i-1]。我们再设一个数组add[i],表示在i这个点向左最多拓展的总和。那么add[i]=max(add[i-1]+b[i],0)-->什么意思呢?如果向左可以多拓展,就尽量的拓展,否则我们就不拓展。每次更新时就是:sum[i+f-1]-sum[i-1]+add[i-1]。
【再想】然而我有些点一直过不了啊。如果我改成截尾取整,一些点错了;改成四舍五入,另外一些不同的点错了。这一度让我怀疑是否是数据出错了。后来经过研究才发现,二分是有点问题的:设最终答案是10,当前l=9.9,r=10。自然,l是不会等于10的,而是越来越接近。但是在返回的时候,我们不一定是10,而是9.99999999999。结果截尾取整后,答案就会变成9了。
【改进】也算是“打点”吧,我在二分时返回r值就过了。但这不是完美的解决啊。询问了RZZ大牛:原来,我们可以把结果加上0.0000000001,然后二分再开大精度即可。(当然你得事先想到这种可能)
【代码】
#include<cstdio>#include<algorithm>#include<cmath>using namespace std;typedef long long ll;const int maxn=100005;int n,f,i,Min,Max,a[maxn],cnt;double ans,b[maxn],sum[maxn],add[maxn];bool check(double p){ int i; for (i=1;i<=n;i++) b[i]=a[i]-p; for (i=1;i<=n;i++) { add[i]=add[i-1]+b[i];if (add[i]<0) add[i]=0; sum[i]=sum[i-1]+b[i]; } for (i=1;i<=n-f+1;i++) if (sum[i+f-1]-sum[i-1]+add[i-1]>=0) return true; return false;}double erfen(double l,double r){ double mid=(l+r)/2; if (r-l<=0.0001) return r; if (check(mid)) return erfen(mid,r); return erfen(l,mid);} int main(){ freopen("cowfnc.in","r",stdin); freopen("cowfnc.out","w",stdout); scanf("%d%d",&n,&f); for (i=1;i<=n;i++) { scanf("%d",&a[i]); Min=min(Min,a[i]); Max=max(Max,a[i]); } ans=erfen(Min,Max)*1000; printf("%d",int(ans)); return 0;}
- usaco 2003 月赛 Best Cow Fences & poj2018 题解
- poj2018 Best Cow Fences
- poj2018 Best Cow Fences
- POJ2018 Best Cow Fences DP或二分
- poj2018 Best Cow Fences(直接求斜率)
- poj2018 Best Cow Fences(求至少k个连续数 使得平均值最大)
- usaco 月赛 2008 January Best Cow Line 贝茜的晨练计划 题解
- usaco 月赛 2007 Cow Traffic 题解
- poj 2018 Best Cow Fences
- poj 2018 Best Cow Fences
- poj 2018 Best Cow Fences
- POJ 2018 Best Cow Fences
- POJ 2018 Best Cow Fences
- POJ 2018 Best Cow Fences
- poj 2018 Best Cow Fences
- 【斜率】【poj 2018】Best Cow Fences
- POJ - 2018 Best Cow Fences(DP)
- POJ 2018 Best Cow Fences 笔记
- UISeachBar 常用方法
- python中常用的正则表达式
- timeit 模块
- Emacs中JDEE的配置
- 马斯洛需求层次理论与消费者需求
- usaco 2003 月赛 Best Cow Fences & poj2018 题解
- Java实现存储过程的sql处理
- 关于最简单的控件使用注意点
- 使用MyEclipse自动生成WebService服务端代码
- 迅雷导致sql数据库无法启动
- C++ class中static私用成员
- POJ 2019 Cornfields(简单二维RMQ)
- 数据库自动备份
- 【热门收藏】iOS开发人员必看的精品资料(100个)