POJ 2976 Dropping tests、3111 K Best (二分搜索)

本文介绍了两种算法问题:一种是在限定条件下最大化平均得分的问题,通过贪婪算法实现;另一种是选择价值重量比最高的K个物品的问题,同样采用类似的方法解决。文章提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Dropping tests
Time Limit: 1000MS Memory Limit: 65536K
Total Submissions: 7327 Accepted: 2548

Description

In a certain course, you take n tests. If you get ai out of bi questions correct on test i, your cumulative average is defined to be

.

Given your test scores and a positive integer k, determine how high you can make your cumulative average if you are allowed to drop any k of your test scores.

Suppose you take 3 tests with scores of 5/5, 0/1, and 2/6. Without dropping any tests, your cumulative average is . However, if you drop the third test, your cumulative average becomes .

Input

The input test file will contain multiple test cases, each containing exactly three lines. The first line contains two integers, 1 ≤ n ≤ 1000 and 0 ≤ k < n. The second line contains n integers indicating ai for all i. The third line contains n positive integers indicating bi for all i. It is guaranteed that 0 ≤ ai ≤ bi ≤ 1, 000, 000, 000. The end-of-file is marked by a test case with n = k = 0 and should not be processed.

Output

For each test case, write a single line with the highest cumulative average possible after dropping k of the given test scores. The average should be rounded to the nearest integer.

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

把式子展开然后就发现是个贪心了 - - Orz

两道一样的题 就贴下代码好了

AC代码如下:

//
//  Created by TaoSama on 2015-04-28
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, k, a[1005], b[1005];
double y[1005];

bool check(double x) {
    for(int i = 1; i <= n; ++i)
        y[i] = a[i] - x * b[i];
    sort(y + 1, y + 1 + n);

    /*for(int i = 1; i <= n; ++i)
        cout<<y[i]<<' ';
    cout<<endl<<endl; */

    double sum = 0;
    for(int i = 1; i <= n - k; ++i)
        sum += y[n - i + 1];
    return sum >= 0;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    while(cin >> 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 = 1;
        for(int i = 0; i < 100; ++i) {
            double mid = (l + r) / 2;
            if(check(mid)) l = mid;
            else r = mid;
        }
        cout << (int)(l * 100 + 0.5) << '\n';
    }
    return 0;
}

K Best
Time Limit: 8000MS Memory Limit: 65536K
Total Submissions: 6638 Accepted: 1753
Case Time Limit: 2000MS Special Judge

Description

Demy has n jewels. Each of her jewels has some value vi and weight wi.

Since her husband John got broke after recent financial crises, Demy has decided to sell some jewels. She has decided that she would keep k best jewels for herself. She decided to keep such jewels that their specific value is as large as possible. That is, denote the specific value of some set of jewels S = {i1i2, …, ik} as

.

Demy would like to select such k jewels that their specific value is maximal possible. Help her to do so.

Input

The first line of the input file contains n — the number of jewels Demy got, and k — the number of jewels she would like to keep (1 ≤ k ≤ n ≤ 100 000).

The following n lines contain two integer numbers each — vi and wi (0 ≤ vi ≤ 106, 1 ≤ wi ≤ 106, both the sum of all vi and the sum of all wi do not exceed 107).

Output

Output k numbers — the numbers of jewels Demy must keep. If there are several solutions, output any one.

Sample Input

3 2
1 1
1 2
1 3

Sample Output

1 2

好像100次T了 - - 然后改成了50次 Orz

AC代码如下:

//
//  Created by TaoSama on 2015-04-28
//  Copyright (c) 2015 TaoSama. All rights reserved.
//
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7;
const int N = 1e5 + 10;

int n, k, v[N], w[N];
struct Jewel {
    int id;
    double y;
    bool operator<(const Jewel& rhs) const {
        return y > rhs.y;
    }
} a[N];

bool check(double x) {
    for(int i = 1; i <= n; ++i) {
        a[i].id = i;
        a[i].y = v[i] - x * w[i];
    }
    sort(a + 1, a + 1 + n);
    double sum = 0;
    for(int i = 1; i <= k; ++i) sum += a[i].y;
    return sum >= 0;
}

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//  freopen("out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; ++i) scanf("%d%d", v + i, w + i);

    double l = 0, r = 1e7 + 1;
    for(int i = 0; i < 50; ++i) {
        double mid = (l + r) / 2;
        if(check(mid)) l = mid;
        else r = mid;
    }

    for(int i = 1; i <= k; ++i)
        printf("%d%c", a[i].id, i == k ? '\n' : ' ');
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值