51nod 1257 背包问题 V3(这不是背包问题是二分)

Posted Gealo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 1257 背包问题 V3(这不是背包问题是二分)相关的知识,希望对你有一定的参考价值。

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1257

题解:不能按照单位价值贪心,不然连样例都过不了

要求的r=sum(x[i]*p[i])/sum(x[i]*w[i])不妨设一个辅助函数

z(l)=sum(x[i]*p[i])-l*sum(x[i]*w[i]),

如果z(l) > 0 即sum(x[i]*p[i])-l*sum(x[i]*w[i])>0-->sum(x[i]*p[i])/sum(x[i]*w[i])>l也就是说存在

比当前更大的l值也就是所要求的最大值r,于是二分一下答案就行了。

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
const int M = 5e4 + 10;
struct TnT {
    int w , p;
    double r;
}T[M];
int n , k;
ll fz , fm;
bool cmp(TnT x , TnT y) {
    return x.r > y.r;
}
ll gcd(ll a , ll b) {
    return (b > 0) ? gcd(b , a % b) : a;
}
bool check(double l) {
    for(int i = 0 ; i < n ; i++) {
        T[i].r = 1.0 * T[i].p - 1.0 * T[i].w * l;
    }
    sort(T , T + n , cmp);
    double sum = 0.0;
    fz = 0 , fm = 0;
    for(int i = 0 ; i < k ; i++) {
        fz += T[i].p;
        fm += T[i].w;
        sum += T[i].r;
    }
    if(sum >= 0) return true;
    return false;
}
int main() {
    cin >> n >> k;
    for(int i = 0 ; i < n ; i++) {
        cin >> T[i].w >> T[i].p;
    }
    double l = 0.0 , r = 50000.0;
    ll up , down;
    for(int i = 0 ; i <= 50 ; i++) {
        double mid = (l + r) / 2;
        if(check(mid)) {
            l = mid;
            up = fz , down = fm;
        }
        else r = mid;
    }
    ll gg = gcd(up , down);
    cout << up / gg << ‘/‘ << down / gg << endl;
    return 0;
}

以上是关于51nod 1257 背包问题 V3(这不是背包问题是二分)的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1257 背包问题 V3(分数规划)

51nod 1257 01分数规划/二分

1257 背包问题 V3——分数规划

51Nod 1085 背包问题 (01背包)

51nod 1086 背包问题 V2(二进制优化多重背包)

[51nod1597]有限背包计数问题