zoukankan      html  css  js  c++  java
  • [USACO12FEB]牛券Cow Coupons(堆,贪心)

    [USACO12FEB]牛券Cow Coupons(堆,贪心)

    题目描述

    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?

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

    输入输出格式

    输入格式:

    • 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.

    输出格式:

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

    输入输出样例

    输入样例#1:

    4 1 7
    3 2
    2 2
    8 1
    4 3

    输出样例#1:

    3

    说明

    FJ has 4 cows, 1 coupon, and a budget of 7.

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

    堆模拟反悔操作

    很容易发现直接贪心是错误的,因为我们有总钱数的限制。
    那么我们可不可以通过调整假的贪心策略来获得正确答案呢?
    先贪心地拿最小的k个优惠价,然后考虑怎么反悔。
    对于两头牛(i,j),假设(i)用了优惠券,(j)没有用,什么情况下会使(j)用优惠券(i)不用更优呢?很简单:(c[i]+p[j]>p[i]+c[j])。用一个堆维护用优惠券的牛,令一个堆维护还未选择的牛。每次考虑未选择的牛是用原价买还是“反悔”。
    不过自己还有一个疑问,每次钱不够的时候就能够break掉了吗?感觉仔细思考了一下并不可以。希望能够解答

    #include<bits/stdc++.h>
    #define lll long long
    using namespace std;
    lll read(){
        lll x=0,w=1;char ch=getchar();
        while(ch>'9'||ch<'0'){if(ch=='-')w=-1;ch=getchar();}
        while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
        return x*w;
    }
    const lll N=50010;
    lll n,k,m,ans;
    bool vis[N];
    struct node{
        lll p,c,v;
    }f[N];
    priority_queue< pair<int,int> >q1,q2;
    bool cmp(node p,node q){return p.c<q.c;}
    int main(){
        n=read();k=read();m=read();
        for(lll i=1;i<=n;i++)f[i].p=read(),f[i].c=read(),f[i].v=f[i].p-f[i].c;
        sort(f+1,f+1+n,cmp);
        for(lll i=1;i<=k;i++){
            if(m<f[i].c){cout<<i-1;return 0;}
            m-=f[i].c;q1.push(make_pair(f[i].v,i));
        }ans=k;
        for(lll i=k+1;i<=n;i++)q2.push(make_pair(-f[i].p,i));
        while(m&&ans!=n){
            lll i=q2.top().second;q2.pop();
            lll j=q1.top().second;q1.pop();
            if(f[j].c+f[i].p>f[i].c+f[j].p){
                if(m<f[j].v+f[i].c)break;
                q1.push(make_pair(f[i].v,i));
                m-=f[j].v+f[i].c;ans++;
            }
            else {
                if(m<f[i].p)break;
                q1.push(make_pair(f[j].v,j));
                m-=f[i].p;ans++;
            }
        }cout<<ans<<endl;
    }
    
  • 相关阅读:
    第36课 经典问题解析三
    第35课 函数对象分析
    67. Add Binary
    66. Plus One
    58. Length of Last Word
    53. Maximum Subarray
    38. Count and Say
    35. Search Insert Position
    28. Implement strStr()
    27. Remove Element
  • 原文地址:https://www.cnblogs.com/lsgjcya/p/9746268.html
Copyright © 2011-2022 走看看