CQBZ 2444 帮忙

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/83817368


帮忙

题目描述
【题目背景】
在高考研讨会上,随着 z 同学对 zn 了解的深入,发现她不仅是一个善良的女孩子,
还 是一个很勤劳的女生,哇塞,这样棒的女生在 21世纪真是太难遇到了,要是可
以娶到这样的 女生,小 z 陷入了无限的 yy 中
高考研讨会进入了尾声,校长一声令下,搬椅子喽~~~~,只见平时道貌岸然的那
些所谓的好学生们一听要干活全跑了,shit~~!!操场上只剩 zn 与 z 同学了,面对成千
上万的椅子, 肿么办~~小 z 突然意识到现在正是奥赛课啊,于是他想到了
hzoi2009 的兄弟们,果然,当小 z 跑到机房,说明来意后,hzoi2009 的兄弟们(还
有个妹子)当时貌似在考试,但都没有半点 迟疑,立马跟随小 z 下楼(小 z 一直
把这件事记在心中,现在回想起来还有点小感动哈)
【题目描述】
面对成千上万的椅子,当然不能用蛮力一个一个的搬了,校长大人提供了一种搬运
车。 椅子们是排成一排的,搬运车一次必须搬不少于 k 个的连续的椅子,消耗的
机油为所搬椅子重量的平均值(总重量比椅子个数)。小 z 想知道搬一次最多能耗
费多少机油,好向校长报销机油费
输入
第一行:整数 n(代表椅子数)与 k(一次搬的最少的椅子数) 接下来 n 行,每行
一个整数 wi,代表椅子的重量
输出
搬一次可能耗费的最多的机油数 ∗ 1000(结果取整)

样例输入
Copy (如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)

10 6
6
4
2
10
3
8
5
9
4
1
样例输出
6500
提示
【数据范围】

对于30%的数据 0 < k < N ≤ 1000

对于100%的数据 0 < k < n < 100000

0 < Wi ≤ 2000

## 法一
惯用的二分平均值,根据正负判断是否可行,为正说明平均值还能更大,为负说明需要缩小

#include<cstdio>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,k,a[maxn];
double s[maxn];
bool check(double d)
{
    for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i]-d;
    double Min=0;
    for(int i=k;i<=n;i++)
    {
        if(s[i]-Min>=0) return 1;
        Min=min(Min,s[i-k+1]);
    }
    return 0;
}
int main()
{
    double l=2000005,r=-1,mid;
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]*=1000,l=min(l,1.0*a[i]),r=max(r,1.0*a[i]);
    while(r-l>1e-6)
    {
        mid=(l+r)/2;
        if(check(mid)) l=mid;
        else r=mid;
    }
    printf("%d",int(l+1e-6));
}


## 法二
类似于最大子段和,i从k扫到n,维护中间遇到的最大的斜率,并记下那个点,
但是其实**这样的做法是有问题的**,因为就算当决策点为下凸壳,仍然无法凭借单调性得到当前点的最优解

#include<cstdio>
#include<algorithm>
using namespace std;
int n,k,a[100005];
double ans;
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]+=a[i-1];
    for(int i=k,tmp=0;i<=n;i++)
    {
        int j=i-k;
        if(1ll*(a[i]-a[j])*(i-tmp)>=1ll*(a[i]-a[tmp])*k) tmp=j;//新增决策点
        ans=max(ans,(a[i]-a[tmp])*1000.0/(i-tmp));
    }
    printf("%d",int(ans));
}


实际上可以构造数据卡掉这种算法,比如:
7 4
10 20 40 10 5 2 50
二分答案为21400,取后5个
上面的程序为21166,取后6个

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/83817368
今日推荐