题意:

给你若n个分数,分子a[i]a[i]a[i],分母b[i]b[i]b[i],使满足公式100⋅∑i=1nai∑i=1nbi100\cdot\tfrac{\sum_{i=1}^{n} a_{i}}{\sum_{i=1}^{n} b_{i}}100⋅∑i=1n​bi​∑i=1n​ai​​,求任意去掉k个分数后,公式结果最大值。

题目:

In a certain course, you take n tests. If you get aia_{i}ai​ out of bib_{i}bi​ questions correct on test i, your cumulative average is defined to be

100⋅∑i=1nai∑i=1nbi100\cdot\tfrac{\sum_{i=1}^{n} a_{i}}{\sum_{i=1}^{n} b_{i}}100⋅∑i=1n​bi​∑i=1n​ai​​

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is 100⋅5+0+25+1+6100\cdot\tfrac{5+0+2}{5+1+6}100⋅5+1+65+0+2​. However, if you drop the third test, your cumulative average becomes 100⋅5+05+1≈83.33≈83100\cdot\tfrac{5+0}{5+1}\approx83.33\approx83100⋅5+15+0​≈83.33≈83.

Input

The input test file will contain multiple test cases, each containing exactly three lines. The first line contains two integers, 1 ≤ n ≤ 1000 and 0 ≤ k < n. The second line contains n integers indicating ai for all i. The third line contains n positive integers indicating bi for all i. It is guaranteed that 0 ≤ ai ≤ bi ≤ 1, 000, 000, 000. The end-of-file is marked by a test case with n = k = 0 and should not be processed.

Output

For each test case, write a single line with the highest cumulative average possible after dropping k of the given test scores. The average should be rounded to the nearest integer.

Sample Input

3 1
5 0 2
5 1 6
4 2
1 2 7 9
5 6 7 9
0 0

Sample Output

83
100

Hint

To avoid ambiguities due to rounding errors, the judge tests have been constructed so that all answers are at least 0.001 away from a decision boundary (i.e., you can assume that the average is never 83.4997).

分析:

  • 01分数规划:
    简单的来说,就是有一些二元组(ai,bi),从中选取一些二元组,使得∑ai / ∑bi最大(最小)。
    这种题一类通用的解法就是,我们假设x = ∑ai / ∑bi的最大(小)值,那么就有x * ∑ai = ∑bi ,即∑ai - x * ∑bi= 0。也就是说,当某一个值x满足上述式子的时候,它就是要求的值。我们可以想到枚举……不过再想想,这个可以二分答案。
    所以我们直接二分答案,当上述式子>0,说明答案小了,<0则说明答案大了,这样计算即可。
    01分数规划问题相关算法详解

AC代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=1e3+10;
const double eps=1e-4;
int n,m;
double a[M],b[M],c[M];
bool cmp(double u,double v){return u>v;
}
bool dfs(double x){for(int i=0;i<n;i++){c[i]=a[i]-x*b[i];}sort(c,c+n,cmp);double ans=0.0;for(int i=0;i<n-m;i++)ans+=c[i];if(ans>=0) return true;return false;
}
int main(){while(~scanf("%d%d",&n,&m)){if(n==0&&m==0)break;for(int i=0;i<n;i++)scanf("%lf",&a[i]);for(int i=0;i<n;i++)scanf("%lf",&b[i]);double r=0.0,l=1.0;while(l-r>eps){double mid=(r+l)/2;if(dfs(mid)) r=mid;else l=mid;}printf("%.0f\n",r*100);}return 0;
}

基本01分数规划问题

给定 n 个二元组 (ai,bia_{i},b_{i}ai​,bi​ ) aia_{i}ai​是选择此二元组获得的价值(非负),bib_{i}bi​是选择此二元组付出的代价(非负),设 xix_{i}xi​ (xix_{i}xi​ ∈ { 0 , 1 } ) 代表第 i个二元组的选与不选,最大(小)化下式
max(ormax(ormax(or min)min)min) r=∑i=1nai⋅xi∑i=1nbi⋅xir=\tfrac{\sum_{i=1}^{n} a_{i}\cdot x_{i}}{\sum_{i=1}^{n} b_{i}\cdot x_{i}}r=∑i=1n​bi​⋅xi​∑i=1n​ai​⋅xi​​
下面先说最大化

解决方法:二分法

设 r最大值为r∗r^{∗}r∗
r∗r^{∗}r∗=∑i=1nai⋅xi∑i=1nbi⋅xi=\tfrac{\sum_{i=1}^{n} a_{i}\cdot x_{i}}{\sum_{i=1}^{n} b_{i}\cdot x_{i}}=∑i=1n​bi​⋅xi​∑i=1n​ai​⋅xi​​
⇔\Leftrightarrow⇔ ∑ai⋅xi−r∗⋅∑bi⋅xi=0\sum a_{i}\cdot x_{i}-r^{*}\cdot\sum b_{i}\cdot x_{i}=0∑ai​⋅xi​−r∗⋅∑bi​⋅xi​=0
设一个函数,自变量为 r值,
f(r)f ( r )f(r) = ∑ai⋅xi−r∗⋅∑bi⋅xi\sum a_{i}\cdot x_{i}-r^{*}\cdot\sum b_{i}\cdot x_{i}∑ai​⋅xi​−r∗⋅∑bi​⋅xi​

观察这个函数,假如xi{x_{i}}xi​固定,则这个函数就是坐标系中一条直线( y = B − A ⋅ x),每一组xix_{i}xi​对应着一条直线,这些直线斜率非正(因为 − A = − ∑bi⋅xib_{i} ⋅ x_{i}bi​⋅xi​ ≤ 0),纵截距非负(因为 B = ∑ai⋅xi≥0)a_{i}⋅ x_{i} ≥ 0)ai​⋅xi​≥0),如图1。

对于每一条直线,当f(r)=0f ( r ) = 0f(r)=0时,横截距就是这一组的 r,那么r∗r^{*}r∗ 就是每条直线横截距的最大值(每组xix_{i}xi​对应r的最大值)如图2。

在图中上任取一条垂直x轴的竖线,
如果存在直线与这条竖线的交点纵坐标为正,那么最优值一定在当前竖线的右侧;
如果所有直线与这条竖线交点纵坐标为负,那么最优值一定在当前竖线的左侧;
如果所有直线与这条竖线交点纵坐标非正且存在直线与这条竖线交点纵坐标为0,那么当前竖线横坐标即为最优值r∗r^{*}r∗ 。

按照这个思想,可以二分答案r,那么二分时如何进行判断呢?

选择一个 r时需要判断所有 f(r)f ( r )f(r)的最大值是否为0,如果 maxm a xmax {f(r)f ( r )f(r) } > 0则 r < r∗r^{∗}r∗;
怎样求 maxf(r)m a x { f ( r ) }maxf(r)?
f(r)f ( r )f(r) = ∑ai⋅xi−r⋅∑bi⋅xi\sum a_{i}\cdot x_{i}-r\cdot\sum b_{i}\cdot x_{i}∑ai​⋅xi​−r⋅∑bi​⋅xi​
⇔\Leftrightarrow⇔∑(ai−r⋅bi)⋅xi\sum( a_{i}-r\cdot b_{i})\cdot x_{i}∑(ai​−r⋅bi​)⋅xi​
二分一个 r时,每个二元组的(ai−r⋅bi)⋅xi( a_{i}-r\cdot b_{i})\cdot x_{i}(ai​−r⋅bi​)⋅xi​都可以求出,设其为weightiweight_{i}weighti​,现在的目标就是找到一组 xix_{i}xi​使得 ∑ wighti⋅xiw i g h t _{i} ⋅ x_{ i}wighti​⋅xi​ 最大(即求maxf(r)m a x { f ( r ) }maxf(r))。怎么找到这一组xix_{i}xi​,或者直接求得 maxf(r)m a x { f ( r ) }maxf(r) 呢?具体问题具体分析,经常借助最短路算法判断是否存在负环。

二分+01分数规划+最大化平均值 Dropping tests POJ - 2976相关推荐

  1. 转载二分 01 分数规划即最大化平均值的证明0/1分数规划、最优比率生成树、最优比率环

    首页 新随笔 联系 管理 订阅 随笔- 20  文章- 0  评论- 9 [Algorithm]01分数规划--Update:2012年7月27日 [关键字] 0/1分数规划.最优比率生成树.最优比率 ...

  2. 点分治问题 ----------- luoguP2942 [WC2010]重建计划 [点分治 + bfs + 单调队列 + 预处理建树 + 二分 + 01分数规划]

    题目链接 解题思路: 1.对于这个Avgvalue=∑e∈sv(e)∣s∣Avgvalue = \frac{\sum_{e\in s}v(e)}{|s|}Avgvalue=∣s∣∑e∈s​v(e)​ ...

  3. Divide and conquer:Dropping tests(POJ 2976)

    最大化平均值 题目大意:给定你n个分数,从中找出k个数,使∑a/∑b的最大值 这一题同样的也可以用二分法来做(用DP会超时,可见二分法是多么的实用呵!),大体上是这样子:假设最大的平均值是w,那么题目 ...

  4. Bailian4145 放弃考试 POJ2976 ZOJ3068 Dropping tests【二分法+01分数规划】

    4145:放弃考试 总时间限制: 1000ms 内存限制: 65536kB 描述 在一门课程中,一共有n场考试.假如你在i场考试中可以答对bi道题中的ai道,那么你的累计平均分定义为:100·Σai/ ...

  5. POJ-2976 Dropping tests 01分数规划

    题目链接:http://poj.org/problem?id=2976 很典型的01分数规划,sort+二分即可.注意精度问题,这种四舍五入的问题一般都是两种处理方法:1.printf("% ...

  6. poj 2976 Dropping tests 01分数规划

    题目大意: http://poj.org/problem?id=2976 题解: 裸的01分数规划 #include <cstdio> #include <cstring> # ...

  7. 算法提高课-图论-负环-AcWing 1165. 单词环:spfa判正环、二分、01分数规划

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 如何建图? 这样建图.以样例举例.起点是前两个字母,终点是末尾两个字母,边权是字符串的长度. 我们求的是什么呢? 题目要求Σ边权Σ1 ...

  8. 算法提高课-图论-负环-AcWing 361. 观光奶牛:spfa判正环、负环、01分数规划、二分

    文章目录 题目分析 题目链接 题目分析 来源:acwing 分析: 题目要求ΣfiΣgi\frac{\Sigma{f_i}}{\Sigma{g_i}}Σgi​Σfi​​的最大值,这种问题称为01分数规 ...

  9. P1768-天路【负环,SPFA,01分数规划,二分答案】

    正题 题目链接:https://www.luogu.org/problemnew/show/P1768 题目大意 求一条回路使得路上∑vi∑pi\frac{\sum v_i}{\sum p_i}∑pi ...

最新文章

  1. 对ie6、ie7、ff兼容性的详细css hack介绍
  2. PXI和CompactPCI的区别比较
  3. Java中怎样创建线程安全的方法
  4. c语言编制编程语言,C语言CGI编程入门(一)
  5. 【Shell 编程基础第一部分】Shell脚本HelloShell及简单的Shell基础
  6. ebs oracle pl sql开发_ORACLEERP开发基础之EBS开发基础
  7. 精选10款超酷的HTML5/CSS3菜单
  8. Linux fork与vfork的区别
  9. vue个人学习(三)----组件
  10. 交直流配电网潮流计算matlab,干货丨交直流混合配电网潮流计算(含分布式电源)...
  11. 思岚激光雷达rplidar从ROS 1到ROS 2的移植
  12. 【FineReport】常用快捷键
  13. 【数据库查询--电影制片系列】-- 检索出Studio表中制片公司st1的地址。
  14. 如何清理电脑系统缓存
  15. MySQL窗口函数——分组排序函数:number_rank(),rank(),dense_rank()
  16. amd625和mx250比较_笔记本电脑中的1050ti与mx250哪个显卡的性能比较好一些?
  17. 自制 计算机主板,三步教你如何DIY电脑主板和CPU的搭配
  18. Linux使用shell脚本批量拷贝文件
  19. Android-模块化-面向接口编程深度解析,值得收藏
  20. 关于瑞萨RL78系列单片机在线升级

热门文章

  1. java之通过FileChannel实现文件复制
  2. linux之使用md5sum命令比较两个文件是否一样
  3. 怎么查看ubuntu是多少位和常用信息
  4. js监听多个事件_JavaScript中的事件与异常捕获解析
  5. 为什么你闻不到自己胳肢窝的味道?
  6. 有什么看起来很难,但是其实很简单的题目
  7. 要成为年薪五十万的数据分析师,除了技术还需要什么?
  8. dockerfile文件名_Linux云计算教程全套视频合集:Dockerfile详解(一)
  9. sv队列和动态数组的区别_Go 刷 LeetCode 系列:经典(7) 设计双端队列
  10. python统计出现的中文标点_Python处理中文标点符号大集合