zoukankan      html  css  js  c++  java
  • [Usaco2012 Feb]Cow Coupons 买牛 或 牛券

    本人水平有限,题解不到为处,请多多谅解

    本蒟蒻谢谢大家观看

    题目:传送门

    本题时带有反悔操作的贪心

    我们可以先按优惠价给他们排序,可以保证序列值从小到大最优(优惠价比原价小)

    取前k头奶牛(k张优惠券),但不一定会在它们身上用上优惠券之后我们可以用反悔操作但此时一定为最优,再用总钱数不断减去,若当总钱数<0时,我们不用继续往下找了,前k个数一定最小的,所以统计完之后直接return 掉

    若取完前k头牛钱还有剩余的话,我们又分为两种情况

    1:若k之后的当前点不用券,那就要维护一个原价sort,不断贪心

    2:若k之后的当前点要有券,那么用差值维护一个小根堆,不断贪心

    注意记得开long long

    数据范围很大

    code:

     1 #include<bits/stdc++.h>
     2 #pragma GCC optimize(3)
     3 #define int long long
     4 using namespace std; 
     5 const int INF=5e18;
     6 priority_queue<int,vector<int>,greater<int> >q;
     7 int ans=0,n,k,m,hhh;
     8 inline int read(){
     9     int x=0,f=1;char ch=getchar();
    10     while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    11     while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    12     return x*f;
    13 }
    14 struct oo{
    15     int p,c;
    16     bool use;
    17 }cow[51000];
    18 bool cmp1(oo aa,oo bb){
    19     return aa.c<bb.c;
    20 }
    21 bool cmp2(oo aa,oo bb){
    22     return aa.p<bb.p;
    23 }
    24 signed main()
    25 {    
    26     n=read(),k=read(),m=read();
    27     for(int i=1;i<=n;i++){
    28         cow[i].p=read(),cow[i].c=read();
    29     }
    30     sort(cow+1,cow+1+n,cmp1);//按优惠价排列贪心 
    31     for(int i=1;i<=k;i++){
    32         m-=cow[i].c;
    33         if(m>=0){
    34             ans++;
    35         }
    36         else{
    37             printf("%lld
    ",ans);
    38             return 0;
    39         }
    40         q.push(cow[i].p-cow[i].c);//预处理反悔,方便赎回券 
    41     }
    42     sort(cow+1+k,cow+1+n,cmp2);//取完前k头牛之后的,按原价排列(无券可用) 
    43     for(int i=k+1;i<=n;i++){
    44         if(q.empty()){
    45             hhh=INF;//如果堆为空,因为此题要求取min,所以初始最大化 
    46         }
    47         else{
    48             hhh=q.top();//如果堆不为空,取出堆顶 
    49         }
    50         if(hhh+cow[i].c<cow[i].p){
    51         //如果赎回一张券来用给j的话,判断反悔时赎金+使用券后的钱与不用券的值比 
    52             m-=q.top()+cow[i].c;//如果小于,用券给j,记下小值 
    53             q.pop();//出堆 
    54             q.push(cow[i].p-cow[i].c);//继续贪心 
    55             //因为取走了cow[i].p-cow[i].c 所以继续push进堆 
    56         }
    57         else{
    58             m-=cow[i].p;//否则不用券给j,直接累加取最优 
    59         }
    60         if(m>=0){
    61             ans++;//判断此时手上的钱是否大于0,大于0就表示可以买这头牛 
    62         }
    63         else{
    64             printf("%lld
    ",ans);//否则钱不够,后面肯定也买不起,直接break 
    65             return 0;
    66         }
    67     }
    68     printf("%lld
    ",ans);//输出答案即可 
    69     return 0;
    70 }
  • 相关阅读:
    C# dataGridView控件某单元格,间隔地变换背景色
    VS2005 DataGridView 和 GirdView 横向大比拼
    WinForm 修改Internet选项安全属性 。。。。。。。。。。
    [C#]使用HttpWebRequest请求远端服务器时如何加载SSL证书
    C# 采集 :设计一个可超时的阻塞方法
    c# 程序只能运行一次(多次运行只能打开同一个程序) 并激活第一个实例,使其获得焦点,并在最前端显示.
    windows下的正则式工具介绍之一:RegexBuddy
    delegate 与异步调用。。。。。。。。。。。
    C# 轻松实现水印: 利用原图和水印图的重叠 !!!!
    DataGridView常用属性 《一》
  • 原文地址:https://www.cnblogs.com/nlyzl/p/11697432.html
Copyright © 2011-2022 走看看