POJ 3614 Sunscreen [贪心 + 优先队列] 《挑战程序设计竞赛》2.4

题目链接 POJ 3614 Sunscreen
题目大意

有C头牛要涂防晒霜去晒太阳。每头牛需要涂抹的防晒霜的SPF值不同,第i头牛涂抹的防晒霜SPF必须在 [minSPFi,maxSPFi] 之间才能起作用。现在有防晒霜L瓶,每瓶的SPF值为 SPFi ,第i瓶可供 coveri 头牛使用。
现在要求最多能满足多少头牛的需求。

输入格式:

第一行 C, L
接下来2~C+1行, 每行两个数字 minSPFi , maxSPFi
接下来L行, 每行两个数字, SPFi , coveri

输出格式:

一个数字, 表示最多能满足多少头牛的需求

题解:

先给牛按照 minSPFi 升序排序, 防晒霜按照 SPFi 升序排序。
需求被满足的牛的数量受限于防晒霜的数量。我们按 SPFi 升序枚举防晒霜, 用贪心的策略将它涂在不同的牛身上。
这里的贪心策略是: 当一瓶防晒霜同时符合多头牛的需求时, 将其涂在 maxSPFi 最小的牛身上。
因为防晒霜是按升序排序的, 对于 maxSPFi 更大的牛,或许在此在之后还有 SPFi 更大的防晒霜也可以满足这头牛, 但却不一定能符合当前 maxSPFi 较小的牛了。
对于每瓶防晒霜 bottlei , 将 minSPF 小于 SPFi 的牛的 maxSPF 放入优先队列, 每次取出队列中 maxSPF 的最小值 min_maxSPF 。如果 min_maxSPF 小于当前 SPFi 则这个牛已经不可能再找到符合它需求的防晒霜了。然后把 bottlei coveri 用完, 或者队列为空, 则当前这瓶防晒霜已经处理完毕, 开始枚举下一瓶。
对于处理前一瓶时队列中剩下的 maxSPF , 这些牛的 minSPF 也一定小于当前防晒霜的 SPF , 所以它们的处理方式与新加入队列的 maxSPF 是相同的。

代码:

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstdio>
#define MAXL 2510
#define MAXC 2510
using namespace std;

typedef pair<int, int> Pair;
int C, L;
Pair cow[MAXC];
Pair bottle[MAXL];
priority_queue<int, vector<int>, greater<int> > q;

int main() {
    cin >> C >> L;
    for (int i = 0; i < C; i++)
        cin >> cow[i].first >> cow[i].second;
    for (int i = 0; i < L; i++)
        cin >> bottle[i].first >> bottle[i].second;

    sort(cow, cow+C);
    sort(bottle, bottle+L);

    int cur = 0;
    int ans = 0;
    for (int i = 0; i < L; i++) {
        while (cur < C && cow[cur].first <= bottle[i].first)
            q.push(cow[cur++].second);
        while (!q.empty() && bottle[i].second) {
            int min_MaxSPF = q.top();
            q.pop();
            if (min_MaxSPF >= bottle[i].first) {
                ans++;
                bottle[i].second--;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

参考:码农场 hankcs.com

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值