7-15 做梦的wls (20 分)

wls做了一个梦,梦里他拥有了超能力。
森林里有n棵树,同时wls有两种能力,两种能力总共可以使用m次。

  • 选择一棵树,将其从森林中删除
  • 选择森林中的一棵树,将它的高度提升1,但是每颗树只能被提高k次,k次以后这个能力就对这棵树失效了。
  • 现在他想让森林树木高度的平均值尽可能的大。

输入格式:

第一行n,k,m,含义同上,下一行,给出n棵树木的初始高度
(所有数字均小于1e5)

输出格式:

输出最大的平均值,保留两位小数。

输入样例:

2 4 6
4 7
4 2 6
1 3 2 3

输出样例:

11.00
5.00

感觉这类的题目挺有意思的,想出来挺有成就感的,在这里分享一下我的思路。

首先我们看到题目我刚开始想的是把小的都踢掉,然后对一个进行升高,但是很快就排除了因为有6 7这样的例子,然后又想用两个选择去判断,就是先对小的看是否要踢出他,判断的依据是把他删了的结果,然后给他加1的结果,但是这样的例子显然不行,因为如果有2 9000 99999,2,3,4的话这样的题解就错了,很明显我们没有看该过程对后面数据的影响,然后我就想动态规划了,但是这10000个数据去动态规划多少有点超时,所以我就想把所有精力集中到是否该删除这个结点,此时我就想到了控制变量法了,如果我删除这个剩下的操作都用+1,和这个不删除都加1,如果前面的大我就把他删了,因为我删了之后可以更大,每一个都这样去迭代,最终就得出了最优解吧(应该是的滑稽😆) ,根据这个我们写出了下面的代码。

#include <bits/stdc++.h>
using namespace std;
int main(){
    int n,m,k;
    scanf("%d%d%d",&n,&m,&k);
    int i;
    int a[n];
    double sum=0;
    for(i=0;i<n;i++){
        scanf("%d",&a[i]);
        sum=sum+a[i];
    }
    sum=sum/n;//平均值
    sort(a,a+n);//排好序
    int s;
    double lans,rans;//不删除和删除的结果
    int take=n*m;//忽略操作数,我能进行第一种操作的最大次数
    i=0;//该删除的结点
    int temp=n-1;
    int t;
    while(k){
        s=min(k,n*m);//得到我能进行第一次操作的最大数
        lans=(double)s/n+sum;//不删除的结果
        if(n-1>0){
            t=min(k-1,(n-1)*m);
            rans=(sum*n-a[i])/(n-1)+(double)t/(n-1);//删除的结果
        }
        else rans=-1;//到了只有一个就只能加了。
        if(lans>rans){
            sum=sum+(double)s/n;
            break;
        }
        else {//删除该结点之后的平均值,便于进行下一次操作
            sum=(sum*n-a[i])/(n-1);
            i++;//到达该删除结点的坐标
            n--;//人数少了一个
        }
        k--;//操作数减1
    }
    printf("%.2lf",sum);
    system("pause");
}

1000ms的用了7ms,今晚加鸡腿。 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值