嘘~ 正在从服务器偷取页面 . . .

POJ2976 Dropping tests 题解


POJ2976 Dropping tests 题解

题目链接:POJ2976 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

.

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

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 ≤ aibi ≤ 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.

经典的01分数规划问题

注意到题目要求的就是选 $n-k$ 个物品使得

尽可能的大

不妨假设

移项可得

于是可以二分一个 $x$

每次暴力检验 $ps[i] = a_i - xb_i$

注意要排个序然后取最大的 $n-k$ 个 $ps[i]$

时间复杂度 $O(\log_2 10^6 \times Q n \log n)$

代码:

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <iomanip>
using namespace std;
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
#define N (int)(2e3+15)
const double eps=1e-13;
int n,k,a[N],b[N];
double ps[N];
bool ck(double x)
{
    for(int i=1; i<=n; i++)
        ps[i]=a[i]-x*b[i];
    sort(ps+1,ps+1+n);
    double res=0;
    for(int i=k+1; i<=n; i++)
        res+=ps[i];
    return res>=0;
}
signed main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    cout << fixed << setprecision(0);
    // freopen("check.in","r",stdin);
    // freopen("check.out","w",stdout);
    while(cin >> n >> k && n)
    {
        for(int i=1; i<=n; i++) cin >> a[i];
        for(int i=1; i<=n; i++) cin >> b[i];
        double l=0,r=1;
        while(r-l>1e-6)
        {
            double mid=(l+r)/2;
            if(ck(mid))l=mid;
            else r=mid;
        }
        cout << l*100 << endl;
    }

    return 0;
}

文章作者: q779
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 q779 !
评论
  目录