Hack 【二分答案】

题意:给出n门课程,每一门课程考的分数,每一门课程的学分,求最多删去k组数据之后能够得到的最大加权平均数

先开一个数组x[],其中x[i]=1代表没有删除这门课程,x[i]=0表示删除了这门课程

然后p[i]=R*c[i]-c[i]*s[i]=c[i]*(R-s[i])

又因为满分为100分,就在0.0在100.0二分来找 再将p数组降序排列,ans为其前n-k个数的和, 如果ans-0>eps,那么l=mid, 如果ans-0<eps,那么r=mid

因为p[]数组是按照降序排列的,所以ans应该是递减的,大概是像这幅图一样

 貌似这样理解有问题,再想一想先-----

下面是学习的代码---------------

 1 #include<iostream>  
 2 #include<cstdio>  
 3 #include<cstring> 
 4 #include <cmath> 
 5 #include<stack>
 6 #include<vector>
 7 #include<map> 
 8 #include<set>
 9 #include<queue> 
10 #include<algorithm>  
11 using namespace std;
12 
13 typedef long long LL;
14 const int INF = (1<<30)-1;
15 const int mod=1000000007;
16 const int maxn=1000005;
17 double eps=1e-4;
18 
19 int s[maxn],c[maxn];
20 double p[maxn];
21 
22 bool cmp(double a,double b){
23     return a>b;
24 }
25 
26 int main(){
27     int ncase;
28 //    freopen("in.txt","r",stdin);
29 //    freopen("out.txt","w",stdout);
30     scanf("%d",&ncase);
31     for(int t=1;t<=ncase;t++){
32         int n,k;
33         scanf("%d %d",&n,&k);
34         for(int i=1;i<=n;i++) scanf("%d",&s[i]);
35         for(int i=1;i<=n;i++) scanf("%d",&c[i]);
36         
37         double l=0.0,r=100.0,mid;
38         
39         while((r-l)>eps){
40              mid=(l+r)/2;
41             
42             for(int i=1;i<=n;i++) p[i]=(double)c[i]*(double)(s[i]-mid);
43             
44             sort(p+1,p+n+1,cmp);
45             
46             double ans=0.0;
47             for(int i=n-k;i>=1;i--) ans+=p[i];
48             
49             if(ans-0>eps) l=mid;
50             else r=mid;
51         }
52         
53         printf("Case #%d:
",t);
54         printf("%.3lf
",mid);        
55     }
56     return 0;
57 }
View Code
原文地址:https://www.cnblogs.com/wuyuewoniu/p/4451779.html