zoukankan      html  css  js  c++  java
  • [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<=10^9)。FJ有K张优惠券,使用优惠券购买第i头奶牛时价格会降为Ci(1<=Ci<=Pi),每头奶牛只能使用一次优惠券。FJ想知道花不超过M(1<=M<=10^14)的钱最多可以买多少奶牛?

    输入输出格式

    输入格式:

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

    说明

    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.


    背景

      当我开始写题解的时候,绝对是我DP写挂了,来换心情的。。。。

      大概是前天的时候,学长讲了这道题,昨天写了进阶版的题解。

      有人跟我说不太懂可反悔的贪心是什么,所以我就来整理一下。


    可反悔的贪心

      贪心大家都了解吧,就是选择当前的最优策略,整合后形成最优解。

      但是这个时候我们可以发现一个问题:

          如果局部最优解与形成整体最优解的情况矛盾怎么办?

      举个例子具体理解一下,

        a有两种选择x1,x2;b有两种选择,y1,y2

        假设,让a满足最优的解法是选择x1,但是使得整体最远的解法则是在a处选择x2.

      那么我们怎么样才能使得这种策略能够被选到呢?

      搜索算法自然是可以做到的,但是一旦数据范围变大就炸掉了。

      那么究竟该怎么办呢?

      我们来仔细思考一下,阻挡我们使用贪心的最大问题是什么?

          是不是一旦局部最优解不是整体最优解,就完全错误?    

          那么假设我们可以时光回溯,回到错误的点修改答案是不是就正确了呢?

      好的,那么只要我们记录一下当前策略与未来策略的差值,当出现问题的时候,直接修改就ok了。

      关于实现问题,就是使用堆栈处理,一般是大根堆。

      这就是可修改的贪心。


    思路分析

      在这道题,我们可以发现,对于每一头牛来说,其实都有两个状态。

          那么我们就可以把两个状态当作是当前可以选择的策略,用优惠券和不用优惠券。

      接下来跑一次可反悔的贪心就ok。

      然后我们就会发现一个问题, 优惠券是有数量的。

      这个也好处理,我们优先处理使用优惠券之后最便宜的几头牛,然后选择剩下的牛中不用券最便宜的。

      之后判断要不要将用过的一张券转用给一头新的牛。

      思路就是开一个大根堆,然后依次push进去p[i] - c[i]

      取出使用即可。


    代码实现

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    #include<algorithm>
    #include<queue>
    #define ll long long
    using namespace std;
    
    int n,k;
    ll m;
    struct ss{
        ll p,c;
    }cow[50001];
    priority_queue<long long,vector<long long>,greater<long long> > q;
    
    int cmp(ss a,ss b) {
        return a.c<b.c;
    }
    
    int cmmp(ss a,ss b) {
        return a.p<b.p;
    }
    
    int main()
    {
        scanf("%d%d%lld",&n,&k,&m);
        for(int i=1;i<=n;i++) 
            scanf("%lld%lld",&cow[i].p,&cow[i].c);
        sort(cow+1,cow+n+1,cmp);
        ll sum=0;
        for(int i=1;i<=k;i++) {
            sum+=cow[i].c;
            if(sum>m) {
                cout<<i-1<<endl;
                return 0;
            }
            q.push(cow[i].p-cow[i].c);
        }
        sort(cow+k+1,cow+n+1,cmmp);
        for(int i=k+1;i<=n;i++) {
            if(cow[i].p-cow[i].c>q.top()) {
                sum+=q.top();
                q.pop();
                q.push(cow[i].p-cow[i].c);
                sum+=cow[i].c;
            }
            else 
                sum+=cow[i].p;
            if(sum>m) {
                cout<<i-1<<endl;
                return 0;
            }
        }
        cout<<n<<endl;
        return 0;
    }
  • 相关阅读:
    CSS选择器
    CSS框模型
    AJAX
    HTML 表单
    二叉树
    词嵌入、word2vec
    双向、深层循环神经网络
    20201012----每天都在进步吗?
    20201012--环境搭建
    20201011--记录一下
  • 原文地址:https://www.cnblogs.com/qxyzili--24/p/11200184.html
Copyright © 2011-2022 走看看