【POJ 2976】Dropping tests

【题目】

传送门

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} 100i=1nbii=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 1005+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 1005+15+083.3383.

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=nk

那么应该有 a 1 + a 2 + . . . + a t b 1 + b 2 + . . . + b t &gt; = m i d \frac{a_1+a_2+...+a_t}{b_1+b_2+...+b_t}&gt;=mid b1+b2+...+bta1+a2+...+at>=mid

移项得 ( a 1 + a 2 + . . . + a t ) &gt; = ( b 1 + b 2 + . . . + b t ) ⋅ m i d (a_1+a_2+...+a_t)&gt;=(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 ) &gt; = 0 (a_1-b_1\cdot mid)+(a_2-b_2\cdot mid)+...+(a_t-b_t\cdot mid)&gt;=0 (a1b1mid)+(a2b2mid)+...+(atbtmid)>=0

到现在就很显然了吧,直接记录一下 a i − b i ⋅ m i d a_i-b_i\cdot mid aibimid,排序后贪心选取最大的 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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值