POJ2976-01分数规划&二分-Dropping tests

15 篇文章 0 订阅
12 篇文章 0 订阅

https://vjudge.net/problem/POJ-2976
给定n个人,有两种分数,a,b
要求你选取一部分,要求 sigma(a)/sigma(b) *100得值最大。
化简式子
这里写图片描述
枚举的mid 不断的逼近最优解。 设定一个精度。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
/* 01分数规划 可以用二分,或者用一种递推。
 思路是 不断的维护一个最优解。
 因为暴力计算最优解,是不可行的,因为他要找那么那么多那么多组合
  而01分数规划是通过对 式子的转化。
  如果 sigma(x1-y1*mid) 大于0,如果当前选择的 分数构成的比例已经大于mid
  也就是说,必然存在一个更优的解(因为我们当前计算就已经比他优了)
  那为什么不用我们 现在计算的那个点呢,
  因为可能有些选择比他更优,
  (如果没有比他更优的话,最后不断的二分,mid会不断的回退到这里)
*/
const int maxn=3000;
const double eps=1e-5;
double  a[maxn];
double  b[maxn];
double aa[maxn];
bool cmp2(double a,double b){
    return a<b;
}
int main()
{   int m,k;
    while(~scanf("%d%d",&m,&k)){
         if(!m&&!k) break;
         for(int i=0;i<m;i++){
              scanf("%lf",&a[i]);
         }
         for(int i=0;i<m;i++){
             scanf("%lf",&b[i]);
         }
         double l=0.0;
         double r=1.0;
         double ans=0;
         double mid;
         while(r-l>=eps){
               mid=(r+l)/2;
               //cout<<mid<<endl;
              double sum=0;
              for(int i=0;i<m;i++){
                 aa[i]=a[i]*1.0-b[i]*mid;
              }
              sort(aa,aa+m,cmp2);
              for(int i=k;i<m;i++){
                  sum+=aa[i];
              }
              if(sum>=0){
                 l=mid;
                 ans=mid;
              }
              else
                r=mid;
         }
         printf("%.0f\n",ans*100);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值