Dropping tests POJ - 2976 (二分搜索 01分數規劃)

題目:

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

題意:

給你兩個數字N和K,代表有N個成績,讓你去掉的成績個數;

下面的兩行代表每一個考試的成績,讓你求出來去除掉K個成績後        的最大值;

思路:

假設 ai / bi >=x,那麼ai - x*bi >= 0;可以直接對於x 進行二分搜索,計算出每一個成績對應的ai - x * bi  的值存成  s[ i ] ;

那麼只需要把計算出來的s數組進行排序,選擇出來最大的前K個數值即可,那麼這K個數值的和就是最大的結果;

注意輸出結果即可;

擴展:

關於01分數規劃,查看了幾篇博客纔有了一點頭緒,那麼就用來理解這一道題的代碼吧;

令F(x)=ai - x*bi,那麼這就可以看成一個一元一次的方程式:F(x)=A - x*B,即F(x)=  - B *x + A;

那麼我們可以知道這條直線和Y軸的交點是 A(A >=0,因爲 A  =  ai ),和X軸的交點是A / B ,斜率是 - B(小於0);

要求出來  x  的最大值,那麼這條直線和X軸的交點就是最大值;

那麼我們就可以來枚舉  x  的值,找出來一條垂直於X軸的直線L,看直線 L 和直線F(x)的交點;

如果交點的值在X軸上邊,那麼這個  x  的值就是小於最大解;

如果交點的值在X軸下邊,那麼這個  x  的值就是大於最大解;

這個就是二分的依據了,成功的解決了代碼中二分依據的問題;

代碼如下:

#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;

const int N=1010;

int n,k;
int a[N],b[N];

double s[N];
double low,high,mid;

int judge(double x)
{
    for(int i=1;i<=n;i++)
    {
        s[i]=a[i]-x*b[i];
    }
    sort(s+1,s+n+1);
    double ans=0;
    for(int i=n;i>k;i--)///選擇最大的K個值;
    {
        ans+=s[i];
    }
    return ans>=0;
}

void solve()
{///01分數規劃;
    low=0;
    high=1;
    while(high-low>1e-6)///注意判斷條件;
    {
        mid=(low+high)/2.0;
        if(judge(mid))
            low=mid;
        else
            high=mid;
    }
    printf("%.0lf\n",low*100);///注意輸出;
    return ;
}

int main()
{
    while(~scanf("%d%d",&n,&k))
    {
        if(n==0&&k==0)///輸入結束;
            break;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&b[i]);
        }
        solve();
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章