牛客第五场多校 A gpa 分数规划(模板)

链接:https://www.nowcoder.com/acm/contest/143/A
来源:牛客网

Kanade selected n courses in the university. The academic credit of the i-th course is s[i] and the score of the i-th course is c[i].

At the university where she attended, the final score of her is 

Now she can delete at most k courses and she want to know what the highest final score that can get.

输入描述:

The first line has two positive integers n,k

The second line has n positive integers s[i]

The third line has n positive integers c[i]

输出描述:

Output the highest final score, your answer is correct if and only if the absolute error with the standard answer is no more than 10

-5

示例1

输入

复制
3 1
1 2 3
3 2 1

输出

复制
2.33333333333

说明

Delete the third course and the final score is 
\frac{2*2+3*1}{2+1}=\frac{7}{3}

备注:

1≤ n≤ 10

5



0≤ k < n

1≤ s[i],c[i] ≤ 10

3

 

题意:给定 n 门课以及它们的学分和绩点,定义总绩点是所有课的加权平均数,给定一个数 k,  你可以删除最多 k 门课,求你的总绩点最大能到多少  1 <=n <=10^5

分析:假设最大总绩点为D,则题中式子可以转化成∑s[i](c[i]-D)=0

观察式子容易看出这是一个分数规划问题,我们可以通过二分D来解答,使左边式子结果最接近0的D即是最大总绩点D

以后类似的分数或者方程式不等式求解问题都可以用这种方式求解

01分数参考博客:https://blog.csdn.net/hhaile/article/details/8883652

AC代码:

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <cstdio>
#include <vector>
#include <string>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define ls (r<<1)
#define rs (r<<1|1)
#define debug(a) cout << #a << " " << a << endl
using namespace std;
typedef long long ll;
const ll maxn = 1e5 + 10;
const ll mod = 1e9 + 7;
ll s[maxn], c[maxn], n, k;
double le, ri, t[maxn];
bool check( double x ) {
    for( ll i = 1; i <= n; i ++ ) {
        t[i] = s[i]*(c[i]-x);
    }
    sort( t+1, t+n+1 );
    double tmp = 0.0;
    for( ll i = k+1; i <= n; i ++ ) {
        tmp += t[i];
    }
    return tmp>0;
}
int main() {
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin >> n >> k;
    for( ll i = 1; i <= n; i ++ ) {
        cin >> s[i];
    }
    for( ll i = 1; i <= n; i ++ ) {
        cin >> c[i];
        ri = max( ri, (double)c[i] );
    }
    double mid;
    while( ri-le > 1e-6 ) {
        mid = (le+ri)/2;
        //debug(mid);
        if( check(mid) ) {
            le = mid;
        } else {
            ri = mid;
        }
    }
    printf("%.10lf\n",mid);
    return 0;
}

  

posted on 2018-08-02 20:35  九月旧约  阅读(283)  评论(0编辑  收藏  举报

导航