POJ2976 Dropping tests (01分数规划)

题目链接
题意:

给出两个长度为 n n n的数组 a a a, b b b,选择 k k k 个下标 p [ 1 ] , p [ 2 ] , . . . p [ k ] p[1],p[2],...p[k] p[1],p[2],...p[k] ,同时将 a a a, b b b 数组中的这些下标删除,得到的数组的权值为

∑ a [ i ] ∑ b [ i ] \frac {\sum a[i]}{\sum b[i]} b[i]a[i] ,求最大权值是多少?

题解:

经典的01分数规划问题,考虑二分最大值 m i d mid mid。 那么式子就要满足 ∑ a [ i ] ∑ b [ i ] ≥ m i d \frac {\sum a[i]}{\sum b[i]} \geq mid b[i]a[i]mid

移项: ∑ ( a [ i ] − m i d ⋅ b [ i ] ) ≥ 0 \sum (a[i]-mid \cdot b[i]) \geq 0 (a[i]midb[i])0 ,此时我们将 a [ i ] − m i d ⋅ b [ i ] a[i]-mid \cdot b[i] a[i]midb[i]看做一个整体进行排序,即我们要选最大的 n − k n-k nk 个数,然后判断是否 ≥ 0 \geq 0 0 ,满足则 l = m i d l=mid l=mid,反之 r = m i d r=mid r=mid

代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<stack>
#include<set>
#include<ctime>
#define iss ios::sync_with_stdio(false)
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
typedef pair<int,int>pii;
const int MAXN=1e5+5;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const double eps = 1e-6;
ll a[MAXN];
ll b[MAXN];
double c[MAXN];
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)&&n&&k)
    {
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++) cin>>b[i];
        double l=0,r=1000;
        while(r-l>eps)
        {
            double mid=(l+r)/2;
            for(int i=1;i<=n;i++) c[i]=a[i]-mid*b[i];
            sort(c+1,c+1+n);
            double s=0;
            for(int i=n;i>k;--i)s+=c[i];
            if(s>=0) l=mid;
            else r=mid;
        }
        printf("%.0f\n",l*100);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值