USACO 2012 Feb Cow Coupons

2590: [Usaco2012 Feb]Cow Coupons

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 349 Solved: 181
[Submit][Status][Discuss]
Description

Farmer John needs new cows! There are N cows for sale (1 <= N <= 50,000), and FJ has to spend no more than his budget of M units of money (1 <= M <= 10^14). Cow i costs P_i money (1 <= P_i <= 10^9), but FJ has K coupons (1 <= K <= N), and when he uses a coupon on cow i, the cow costs C_i instead (1 <= C_i <= P_i). FJ can only use one coupon per cow, of course. What is the maximum number of cows FJ can afford? PROBLEM NAME: coupons

FJ准备买一些新奶牛,市场上有N头奶牛(1<=N<=50000),第i头奶牛价格为Pi(1<=Pi<=10^9)。FJ有K张优惠券,使用优惠券购买第i头奶牛时价格会降为Ci(1<=Ci<=Pi),每头奶牛只能使用一次优惠券。FJ想知道花不超过M(1<=M<=10^14)的钱最多可以买多少奶牛?

Input

  • Line 1: Three space-separated integers: N, K, and M.
  • Lines 2..N+1: Line i+1 contains two integers: (P_i) and (C_i).

Output

  • Line 1: A single integer, the maximum number of cows FJ can afford.

Sample Input

4 1 7
3 2
2 2
8 1
4 3

Sample Output

3

OUTPUT DETAILS: FJ uses the coupon on cow 3 and buys cows 1, 2, and 3, for a total cost of 3 + 2 + 1 = 6.

HINT

Source
Gold

Solution Notes (Nathan Pinsker):

There are several different ways to approach this problem.
One of them stems from the initial idea of picking the lowest-cost cow each time: use all coupons on the cheapest
cows, then buy as many cows as possible without coupons. However, this doesn't quite work: if several cows are very cheap with or without a coupon, and other cows are cheap with a coupon but very expensive without one, we can intuitively see that we would like to use our coupons on the more expensive cows. This leads to the idea of "revoking" a coupon: for cow i, we can pay ((P_i-C_i)) in order to regain one of our coupons (because we are now buying cow i at the "expensive" price).
After purchasing as many cows as possible with coupons, we store their ((P_i-C_i)) values in a heap.
To purchase a remaining cow j, we can either pay (P_j) or (C_j)+ ((P_i-C_i)), where cow i is the top cow in our heap.
This ensures we are always using exactly as many coupons as we can.
For each cow we add to our lineup, we are greedily paying the minimum possible amount for it, so this solution is clearly optimal.

这个题解是从USACO上找的
他什么意思呢

这个题目可以用贪心做
先买下所有用优惠券最便宜的奶牛
然后找出试图用原价比优惠价贵很多的奶牛去替代相对来说优惠价和原价相差较小的奶牛,这样就能省下更多钱
这个东西可以用堆维护

Bruce Merry's solution (implementing this idea) is below:

#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;

typedef long long ll;

struct pqitem{
    ll value;
    int index;
    bool operator<(const pqitem &b)const{
        return value>b.value;
    }
    pqitem(ll value,int index):value(value),index(index){}
};

int main(){
    int N,K;
    ll M;
    cin>>N>>K>>M;
    vector<ll>P(N),C(N);
    for(int i=0;i<N;i++)
        cin>>P[i]>>C[i];
    typedef priority_queue<pqitem> pqtype;
    priority_queue<ll,vector<ll>,greater<ll> >recover;
    pqtype cheap;
    pqtype expensive;
    for(int i=0;i<K;i++)
        recover.push(0LL);
    for(int i=0;i<N;i++){
        cheap.push(pqitem(C[i],i));
        expensive.push(pqitem(P[i],i));
    }
    vector<bool>used(N,false);
    int nused=0;
    while(M>0&&nused<N){
        while(used[cheap.top().index])
            cheap.pop();
        while(used[expensive.top().index])
            expensive.pop();
        if(recover.top()+cheap.top().value<expensive.top().value){
            const pqitem top=cheap.top();
            ll cost=recover.top()+top.value;
            if(M<cost)
                break;
            M-=cost;
            recover.pop();
            recover.push(P[top.index]-C[top.index]);
            used[top.index]=true;
        }
        else{
            const pqitem top=expensive.top();
            ll cost=top.value;
            if(M<cost)
                break;
            M-=cost;
            used[top.index]=true;
        }
        nused++;
    }
    cout<<nused;
    return 0;
}
原文地址:https://www.cnblogs.com/qdscwyy/p/7805960.html