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,今晚加鸡腿。