Dropping tests
Time Limit: 1000MS   Memory Limit: 65536K
     

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

poj 2976 Dropping tests.

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 poj 2976 Dropping tests. However, if you drop the third test, your cumulative average becomes poj 2976 Dropping tests.

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 npositive 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).

Source

题意:n种数,每种数有2个属性,a,b ,选出n-k种数,最大化∑A(n-k)/∑B(n-k)
01分数规划模板题
转换:令∑Ak/∑Bk=ans ,最大化ans
假设只有2个数
(A1+A2)/(B1+B2)=ans
转化:A1+A2=(B1+B2)*ans
去括号、移项:A1-B1*ans+A2-B2*ans=0
假设指定一个f,设ans为最终答案
若f<ans,那么式子>0
若f>ans,那么式子<0
所以二分ans,每次取出前k个最大(Ai-Bi*ans)判断是否>0
若>0,移动下界,否则,移动上界
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,k;
double a[1001],b[1001],tmp[1001];
double l,r,mid,p,ans;
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(!n) break;
        for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
        for(int i=1;i<=n;i++) scanf("%lf",&b[i]);
        l=0;r=1;
        while(fabs(l-r)>0.0001)
        {
            mid=(l+r)/2;p=0;
            for(int i=1;i<=n;i++) tmp[i]=a[i]-mid*b[i];
            sort(tmp+1,tmp+n+1);
            for(int i=n;i>k;i--) p+=tmp[i];
            if(p>0) l=mid;
            else r=mid;
        }
        printf("%.0lf\n",l*100);
    }
}

然而换了换二分姿势就错了,错误1:ans二分前ans要更新为0,防止不能二分

                                    错误2:0.0001精度太小,卡到0.0000001就过了

至于为啥上面0.0001就能A,玄学

以后想着精度卡6、7位就好

错误代码:(就是用新的变量ans,当式子>0时,更新ans,最后输出ans)

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
using namespace std;
int n,k;
double a[1001],b[1001],tmp[1001];
double l,r,mid,p,ans;
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        if(!n) break;
        for(int i=1;i<=n;i++) scanf("%lf",&a[i]);
        for(int i=1;i<=n;i++) scanf("%lf",&b[i]);
        l=0;r=1;
        while(fabs(l-r)>0.0001)
        {
            mid=(l+r)/2;p=0;
            for(int i=1;i<=n;i++) tmp[i]=a[i]-mid*b[i];
            sort(tmp+1,tmp+n+1);
            for(int i=n;i>k;i--) p+=tmp[i];
            if(p>=0) {ans=mid;l=mid+0.0001;}
            else r=mid-0.0001;
        }
        printf("%.0lf\n",ans*100);
    }
}

 

相关文章: