题意:
给你若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=1nbi∑i=1nai,求任意去掉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=1nbi∑i=1nai
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=1nbi⋅xi∑i=1nai⋅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=1nbi⋅xi∑i=1nai⋅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) 呢?具体问题具体分析,经常借助最短路算法判断是否存在负环。