poj2976Dropping tests (二分搜索+还是涉及昨天遇见的o1分数规划)

今年有 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
Hint

为了避免舍入误差带来的二义性,所有答案与除法边界相差至少 0.001 (例如答案永远不可能出现 83.4997)。

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)&&n)
    {
        double  a[1000],b[1000];
        for(int i=0;i<n;++i)
            scanf("%lf",&a[i]);//能做
        for(int i=0;i<n;++i)
            scanf("%lf",&b[i]);//有多少
        double low=0.0,high=100.0,mid,ant;
        while(high-low>0.00001)
        {
            double c[1000];
            ant=0;
            mid=low+(high-low)/2.0;
            for(int i=0;i<n;++i)
                c[i]=a[i]-mid*b[i];
            sort(c,c+n);
            for(int i=k;i<n;++i)
                ant+=c[i];
            if(ant>0)
                low=mid;
            else
                high=mid;
        }
        printf("%.0f\n",mid*100);
          //  cout<<mid<<endl;
    }
    return 0;
}
开始只用了二分搜索,TLE了

#include <iostream>
#include <algorithm>
#include <cstdio>
using namespace std;
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)&&n)
    {
        int  a[1000],b[1000];
        int c[1000];
        for(int i=0;i<n;++i)
        {
            scanf("%d",&a[i]);//能做
            c[i]=i;
        }

        for(int i=0;i<n;++i)
            scanf("%d",&b[i]);//有多少
        double low=0.0,high=100,mid,ant=0;
        while(high-low>0.1)
        {
            mid=low+(high-low)/2.0;

            do
            {
                double aa=0,bb=0,ans;
                for(int i=0;i<n-k;++i)
                  {
                     aa+=a[c[i]];
                    // cout<<c[i]<<' ';
                  }
                 // cout<<endl;
                for(int i=0;i<n-k;++i)
                    bb+=b[c[i]];
                ans=100*(1.0*aa/bb)*1.0;
                if(ans>ant)
                   {
                     ant=ans;
                //  cout<<ant<<endl;
                   }
            }while(next_permutation(c,c+n));
            if(ant>=mid)
                low=mid;
            else
                high=mid;
        }
        printf("%.0lf\n",ant);
            //cout<<ant<<endl;
    }
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值