题解:Luogu_P3045 [USACO12FEB] Cow Coupons G
Luogu_P3045 [USACO12FEB] Cow Coupons G
贪心
Solution
首先有个最初的的想法,将所有牛不用优惠券的价格扔进一个小根堆里,用优惠券的价格扔进一个小根堆,每次比较两个堆顶的价格,选花钱最少的。
看组数据:
3 2 6
5 1
3 1
4 2
按照我们的策略,会选 1、2 号牛,实际如果选 1、3 号牛使用优惠券,剩下的钱可以买下 2 号牛。
问题出在哪里?我们没能正确分配对哪头牛使用优惠券,不过好在这种贪心方法虽然不能保证买到的牛最多,但能保证选到的牛最后都会被买到。(自己讨论一下哪些情况会被选到,发现扔掉都是不优的)
本质的问题出在我们在分配优惠券时,没能考虑每张优惠券能省多少,导致有些优惠券省的钱太少了,买同样的牛,将一些优惠券分配给 \(p_i-c_i\) 更大的牛总价钱会更少。
于是我们再弄一个小根堆,用来存 \(k\) 张优惠券的省钱情况,如果有牛可以更省就把优惠券给新的牛用。
Code
计算细节看代码
//P3045#include <iostream>
#include <cstdio>
#include <map>
#include <queue>#define lld long long
#define pii pair <int, int>using namespace std;inline lld read()
{lld val = 0;bool si = 0;char ch = getchar();for (; !isdigit(ch); ch = getchar())si ^= ch == '-';for (; isdigit(ch); ch = getchar())val = (val << 3) + (val << 1) + (ch ^ 48);return si ? - val : val;
}const int N = 50005;int n, k, p[N], c[N], ans;
lld m;
bool vis[N];priority_queue <pii, vector <pii>, greater <pii> > heap, heac;
priority_queue <int, vector <int>, greater <int> > cost;int main()
{n = read(), k = read(), m = read();for (int i = 1; i <= n; i ++){heap.push(make_pair(p[i] = read(), i));heac.push(make_pair(c[i] = read(), i));}for (int i = 1; i <= k; i ++)cost.push(0);while (!heap.empty() && !heac.empty()){pii nowp = heap.top();if (vis[nowp.second]){heap.pop();continue;}pii nowc = heac.top();if (vis[nowc.second]){heac.pop();continue;}if (nowp.first <= nowc.first + cost.top()){m -= nowp.first;vis[nowp.second] = 1;heap.pop();}else{m -= nowc.first + cost.top();vis[nowc.second] = 1;heac.pop();cost.pop();cost.push(p[nowc.second] - c[nowc.second]);}if (m < 0) break;ans ++;}printf("%d\n", ans);return 0;
}