【题目】
Description
In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be
100 ⋅ ∑ i = 1 n a i ∑ i = 1 n b i 100\cdot \frac{\sum^{n}_{i=1}a_i}{\sum^{n}_{i=1}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 + 2 5 + 1 + 6 = 50 100\cdot \frac{5+0+2}{5+1+6}=50 100⋅5+1+65+0+2=50. However, if you drop the third test, your cumulative average becomes 100 ⋅ 5 + 0 5 + 1 ≈ 83.33 ≈ 83 100\cdot \frac{5+0}{5+1}\approx 83.33\approx 83 100⋅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).
【分析】
大致题意:给出 n n n 个二元组 ( a i , b i ) (a_i,b_i) (ai,bi),给定 k k k,可以从这 n n n 个二元组中丢掉 k k k 个,最后使 a a a 元素之和比上 b b b 元素之和最大
0/1 分数规划简单题
还是采用二分法,假设现在二分到了一个值 m i d mid mid(令 t = n − k t=n-k t=n−k)
那么应该有 a 1 + a 2 + . . . + a t b 1 + b 2 + . . . + b t > = m i d \frac{a_1+a_2+...+a_t}{b_1+b_2+...+b_t}>=mid b1+b2+...+bta1+a2+...+at>=mid
移项得 ( a 1 + a 2 + . . . + a t ) > = ( b 1 + b 2 + . . . + b t ) ⋅ m i d (a_1+a_2+...+a_t)>=(b_1+b_2+...+b_t)\cdot mid (a1+a2+...+at)>=(b1+b2+...+bt)⋅mid
进一步化简得 ( a 1 − b 1 ⋅ m i d ) + ( a 2 − b 2 ⋅ m i d ) + . . . + ( a t − b t ⋅ m i d ) > = 0 (a_1-b_1\cdot mid)+(a_2-b_2\cdot mid)+...+(a_t-b_t\cdot mid)>=0 (a1−b1⋅mid)+(a2−b2⋅mid)+...+(at−bt⋅mid)>=0
到现在就很显然了吧,直接记录一下 a i − b i ⋅ m i d a_i-b_i\cdot mid ai−bi⋅mid,排序后贪心选取最大的 t t t 个,最后判断答案是否大于等于 0 0 0 即可
【代码】
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 1005
#define eps 1e-8
using namespace std;
int n,k,a[N],b[N];
double c[N];
bool check(double mid)
{
int i;
double ans=0;
for(i=1;i<=n;++i)
c[i]=a[i]-b[i]*mid;
sort(c+1,c+n+1);
for(i=n;i>k;--i)
ans+=c[i];
return ans>=0;
}
int main()
{
int i;
while(~scanf("%d%d",&n,&k))
{
if(!n&&!k) break;
for(i=1;i<=n;++i) scanf("%d",&a[i]);
for(i=1;i<=n;++i) scanf("%d",&b[i]);
double l=0,r=1,mid;
while(r-l>eps)
{
mid=(l+r)/2;
if(check(mid)) l=mid;
else r=mid;
}
printf("%.0f\n",l*100);
}
return 0;
}