• Dropping tests [POJ2976] [01分数规划]


    Description

    今年有 n 场 ACM-ICPC 竞赛,小明每场都有资格参加。第 i 场竞赛共有 b[i] 道题。小明预测第 i场他能做出 a[i] 道题。为了让自己看着更“大佬”一些,小明想让自己平均做出的题数越大越好,也就是最大化大佬度,大佬度的定义如下:

    为了达到这个目的,小明决定放弃 k 场比赛的参赛资格。请求出最大的大佬度。

    例如有 3 场小型比赛,题数分别是 5 题、1 题、6 题,小明预测自己分别能做出 5 题、0题、2题。如果每场都参加,那么大佬度是 ,看着不怎么大佬。不过,如果放弃第 3 场比赛,那么大佬度就是 ,看着更加大佬了。

    Input

    输入测试文件含有多组测试,每组有 3 行。第一行有 2 个整数, 1 ≤ n ≤ 1000 和 0 ≤ k < n。第二行有 n 个整数,即每个 a[i]。第三行含有 n 个正整数 b[i]。保证 0 ≤ a[i] ≤ b[i] ≤ 1, 000, 000, 000。文件末尾由 n = k = 0 标识,并且不应该被处理。

    Output

    对于每组测试数据,输出一行整数,即放弃 k 场比赛后可能的最高大佬度。大佬度应该舍入到最近的整数。

    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

    Analysis

    这是一个典型的01分数规划问题,什么意思?

    在两个数列a,b中,选取部分出来,使得∑ai/∑bi最大

    我们采用二分确定下届的方法,设∑ai/∑bi>=x

    则∑(ai/(bi+x))>=0;

    我们按贪心的方法,排序后选取n-m个出来,判断是否正确即可。

    Code

     1 #include<set>
     2 #include<map>
     3 #include<queue>
     4 #include<stack>
     5 #include<cmath>
     6 #include<cstdio>
     7 #include<cstring>
     8 #include<iostream>
     9 #include<algorithm>
    10 #define RG register ll
    11 #define rep(i,a,b)    for(RG i=a;i<=b;++i)
    12 #define per(i,a,b)    for(RG i=a;i>=b;--i)
    13 #define ll long long
    14 #define inf (1<<29)
    15 #define maxn 1005
    16 #define eps 1e-7
    17 using namespace std;
    18 ll n,m;
    19 struct D{
    20     double a,b;
    21 }dat[maxn];
    22 double tmp[maxn];
    23 inline ll read()
    24 {
    25     ll x=0,f=1;char c=getchar();
    26     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    27     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    28     return x*f;
    29 }
    30 
    31 double DD;
    32 
    33 inline int cmp(const D &x,const D &y)
    34 {
    35     return x.a-x.b*DD>y.a-y.b*DD;    
    36 }
    37 
    38 ll check(double lim)
    39 {
    40     DD=lim;
    41     sort(dat+1,dat+1+n,cmp);
    42     double sum=0;
    43     rep(i,1,m)    sum+=dat[i].a-dat[i].b*lim;
    44     return sum>=0;
    45 }
    46 
    47 int main()
    48 {
    49     while(1)
    50     {
    51         double l=0,r=1,ans=0,mid;
    52         n=read(),m=read();m=n-m;
    53         if(!n&&!m)    return 0;
    54         rep(i,1,n)    dat[i].a=read();
    55         rep(i,1,n)    dat[i].b=read();
    56         while(r-l>eps)
    57         {
    58             mid=(l+r)/2.0;
    59             if(check(mid))    ans=mid,l=mid;
    60             else            r=mid;
    61         }
    62         printf("%.0f
    ",ans*100);
    63     }
    64     return 0;
    65 }
    View Code
  • 相关阅读:
    K
    士兵队列训练问题
    分析A + B Problem II
    C++中sort()的用法
    swing初级应用创建一个窗体
    java生成随机数
    JAVA数字格式化
    CodeForces
    POJ
    51Nod
  • 原文地址:https://www.cnblogs.com/ibilllee/p/9263624.html
Copyright © 2020-2023  润新知