P1570 KC喝咖啡

题意:给出n种咖啡材料,每种材料有美味度和消耗时间

   要求下m种材料(只能刚好是m种)

   问下哪些能够得到的平均美味度最大(平均为所有的美味度除以所有的消耗时间)

思路:一开始想的时候,很容易能够想到一种贪心做法,就是按照美味度和消耗时间的比值从大到小排序

   然后取前m个,但是很快就能够发现这种做法是错误的;

   因为除了比值以外,数值的基数也很重要,比如有一个10000美味度的、10000消耗时间的材料

                        然后假如再放一些数值很小很小的材料,就会发现几乎忽略不计

   所以并不是比值越大越好,还要考虑基数

   那这有点难办了,直接贪心做不了,所以我们得换个思路,采用二分的方式

   我们二分对象为平均美味度

   那么如何check呢? 我们需要将原数组做一些改变

   for(int i=1;i<=n;i++)  tmp[i]=G[i].x-mid*G[i].y;

   我们可以根据此式子求出所有的数,然后从大到小排序,找出m个数,假如大于0,则满足,反之不满足

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1000;
 4 double tmp[maxn];
 5 struct node
 6 {
 7     double x,y;
 8 }G[maxn];
 9 int n,m;
10 bool cmp(int t1,int t2)
11 {
12     return t1>t2;
13 }
14 int check(double mid)
15 {
16     for(int i=1;i<=n;i++)
17         tmp[i]=G[i].x-mid*G[i].y;
18     sort(tmp+1,tmp+1+n,cmp);
19     double sum=0;
20     for(int i=1;i<=m;i++){
21         sum+=tmp[i];
22     }
23     if(sum>=0) return 1;
24     else return 0;
25 }
26 int main()
27 {
28     scanf("%d%d",&n,&m);
29     for(int i=1;i<=n;i++){
30         scanf("%lf",&G[i].x);
31     }
32      for(int i=1;i<=n;i++){
33         scanf("%lf",&G[i].y);
34     }
35     double L=0;double R=1000;
36     while((R-L)>=1e-6){
37         double mid=(L+R)/2;
38         if(check(mid)){
39             L=mid;
40         }
41         else R=mid;
42     }
43     printf("%.3f\n",L);
44     return 0;
45 }
View Code

 

posted @ 2020-04-12 11:26  古比  阅读(203)  评论(0编辑  收藏  举报