poj 2976(二分搜索+最大化平均值)

传送门:Problem 2976

参考资料:

  [1]:http://www.hankcs.com/program/cpp/poj-2976-dropping-tests-problem-solution-challenge-programming-contest.html

  [2]:http://www.cnblogs.com/demian/p/7498407.html

有感而发:

  太晚了,身心疲惫,如果明天有空的话,再写上自己对于此题的理解吧,真是个充实愉快的一天啊。

  对了,今天是我们学校70周年校庆,校庆再图书馆前的广场举行,声音震天响,听到外面的热闹声,在和我一个人奋斗相对比,心中难免有些没落,自己选择的ACM,再苦再难也要扛着。

  今天莫名地想到,下一个10周年校庆,我会以何种身份出现在学校呢?

                                  2018.10.17  21:54

AC代码:

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 using namespace std;
 5 #define ll long long
 6 #define INF 0x3f3f3f3f
 7 const int maxn=1e3+50;
 8
 9 int n,k;
10 struct Node
11 {
12     int a,b;
13 }test[maxn];
14 double x;//搜索过程中的准确率
15 //按照对准确率的贡献从小到大排序
16 bool cmp(Node _a,Node _b)
17 {
18     return _a.a-x*_a.b > _b.a-x*_b.b;
19 }
20 //判断是否能获得大于 mid 的准确率
21 bool Check(double mid)
22 {
23     x=mid;
24     sort(test+1,test+n+1,cmp);
25     long long sumA=0;
26     long long sumB=0;
27     for(int i=1;i <= n-k;++i)//去掉后 k 个数后计算准确率
28         sumA += test[i].a,sumB += test[i].b;
29     return 1.0*sumA/sumB >= x;
30 }
31 void Solve()
32 {
33     double l=0,r=1;//准确率的范围为 [l,r)
34     for(int i=1;i <= 100;++i)
35     {
36         double mid=(l+r)/2;
37         if(Check(mid))//如果满足条件,则准确率的范围变为[mid,r)
38             l=mid;
39         else//反之,变为[l,mid)
40             r=mid;
41     }
42     l += 0.005;
43     printf("%d\n",(int)(l*100));
44 }
45 int main()
46 {
47     while(scanf("%d%d",&n,&k), n || k)
48     {
49         for(int i=1;i <= n;++i)
50             scanf("%d",&test[i].a);
51         for(int i=1;i <= n;++i)
52             scanf("%d",&test[i].b);
53         Solve();
54     }
55 }

原文地址:https://www.cnblogs.com/violet-acmer/p/9807411.html

时间: 2024-10-04 23:41:57

poj 2976(二分搜索+最大化平均值)的相关文章

POJ 2976 二分求平均值最大

题意: n个物品有重量w价值v,取出k个使得单位重量价值最大. 思路: 二分,单位重量价值a = sigama(v) / sigama(w),令左<=右,转移方程有 sigama(v - a*w) >= 0.----1 对于二分查找单位重量价值a,排序求出最大k个物品使得sigama(v - a*w)最大. 此时: 若条件1满足,则显然存在更好的方案,因为至少还有该方案. 若条件1不满足,则不存在更好的方案: 反证:现有 sigama(v1 - a1*w1) < 0 即 a1 >

POJ 2976 3111(二分-最大化平均值)

POJ 2976 题意 给n组数据ai,bi,定义累计平均值为: 现给出一个整数k,要求从这n个数中去掉k个数后,最大累计平均值能有多大?(四舍五入到整数) 思路 取n?k个数,使得累计平均值最大. 定义C(x)表示能否取得n?k个数,使得累计平均值≥x.然后二分搜索最大的x. 可以这样判断可行性: 只需要从大到小选取n?k个(100?ai?x?bi)并求和sum,根据sum≥0来判断(上述的S表示n?k个元素下标的集合) #include <iostream> #include <al

POJ 3111 K Best &amp;&amp;NYOJ 914 (二分+ 贪心,最大化平均值)

链接:NYOJ:click here, POJ:click here 题意:(最大化平均值,挑战编程P143) 有n个物品的重量和价值分别是w[i]和v[i],从中选出K个物品使得单位重量的价值最大.(1<=k<=n<=10^41<=w[i],v[i]<=10^6) 一般想到的是按单位价值对物品排序,然后贪心选取,但是这个方法是错误的,比如对nyoj的例题来说,从大到小地进行选取,输入的结果是5/7=0.714对于有样例不满足.我们一般用二分搜索来做(其实这就是一个01分数规

poj 3111 K Best 最大化平均值 二分思想

poj 3111 K Best 最大化平均值 二分思想 题目链接: http://poj.org/problem?id=3111 思路: 挑战程序竞赛书上讲的很好,下面的解释也基本来源于此书 设定条件C(x):=可以选择使得单位重量的价值不小于x 如何判定C(x)是否可行 假设选了某个物品的集合是S,那么单位重量的价值是:\[ \sum\limits_{i \in S} {v_i } /\sum\limits_{i \in S} {w_i } \] 因此就变成了判断是否存在S满足下面的条件:\[

POJ 3111 K Best 二分 最大化平均值

1.题意:给一共N个物品,每个物品有重量W,价值V,要你选出K个出来,使得他们的平均单位重量的价值最高 2.分析:题意为最大化平均值问题,由于每个物品的重量不同所以无法直接按单位价值贪心,但是目标值有界且能判断与最后答案的大小关系,所以用二分来做 3.代码: 1 # include <iostream> 2 # include <cstdio> 3 # include <cmath> 4 # include <algorithm> 5 using names

POJ 3111 K Best(最大化平均值)

题目链接:click here~~ [题目大意]有n个物品的重量和价值分别是Wi和Vi,从中选出K个物品使得单位重量的价值最大,输出物品的编号 [解题思路]:最大化平均值的经典.参见click here~~ 代码: //#include <bits/stdc++.h> #include <stdio.h> #include <math.h> #include <string.h> #include <iostream> #include <

二分算法的应用——最大化平均值

最大化平均值 有n个物品的重量和价值分别wi 和 vi.从中选出 k 个物品使得 单位重量 的价值最大. 限制条件: 1 <= k <= n <= 10^4 1 <= w_i <= v_i <= 10^6 输入:n = 3k = 2{W, V} = {(2,2), (5,3), (2,1)} 输出:0.75 (如果选0号和2号,平均价格是 (2 + 1) / (2 + 2) = 0.75) 题解: 一般先想到的肯定是:把物品按照  单位价值  进行排序,然后从大到小贪心

【二分查找-最大化平均值】POJ2976 - Dropping Test

[题目大意] 给出n组ai和bi,去掉k个使得a的总和除以b的总和最大. [思路] 也就是取(n-k)个数,最大化平均值,见<挑战程序设计竞赛>P144,最后公式为c(x)=((ai-x*bi)从大到小排列的前(n-k)个的和不小于0) 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath>

poj 2456 二分法 最大化最小值

题目:http://poj.org/problem?id=2456 重新练习下二分法,发现还是手速不够 从这道题学到一下几点: 1.线性分几段的方法,看我的Judge()代码: 2.二分的while()最终打印的是down,而不是mid(我代码里写的是ans),或者up, 这么想:跳出循环的时候,假设while里的判断,Judge(ans)==1,那么down是正确解,up不是 Judge(ans)==0,那么ans跟up都不是正确解 综上,打印down才能输出正确解 3.调了好一会二才发现的b