【贪心】兔警官朱迪买礼物

来源:互联网 发布:大唐卫星手机网络电视 编辑:程序博客网 时间:2024/05/17 08:39

传送门:https://vijos.org/d/jcsy/p/58b2b8bad3d8a123ab08db9f
这是一道贪心题,主要由2部分组成
1、首先最优情况必定是k张优惠券全部用完,那么先按优惠价排序,排出来前k个优惠价之和如果比m大,则从小到大按优惠价能买几个买几个,然后输出
2、然后考虑如果步骤1后前k个都买下并还有钱剩余,则可能可以再多买,

但是:

前k个必定不能扔掉:一旦某个被扔掉,则只能省下1张优惠券,这张优惠券用于新的物品要花的钱必定比留下那个扔掉的要多
所以要加入新的只有两种可能:
(1)从已有的取出一张优惠券用于加入新的物品(此时新的优惠价要最小,并且被取出优惠券的物品优惠价与原价之差要最小)
(2)用原价加入新的物品(此时新的原价要最小)
从(1)(2)中取较优状态用于加入
那么为了维护已加入物品优惠价与原价之差最小,可以用堆

以下代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;#define MAX 100000000000000007#define LL long longpriority_queue< LL,vector<LL>,greater<LL> > h;LL n,m,k,s,a_xb,b_xb,ans;bool f[100005];struct price{    LL x,y,z;    bool operator <(const price &s)const{        return y<s.y;    }}a[100005],b[100005];bool cmp(struct price x,struct price y){    return x.x<y.x;}int main(){    cin>>n>>m>>k;    for (int i=1;i<=n;i++){        cin>>a[i].x>>a[i].y;        a[i].z=i;    }    sort(a+1,a+n+1);    for (int i=1;i<=m;i++){        if (s+a[i].y<=k){            s+=a[i].y;            h.push(a[i].x-a[i].y);        }        else{            cout<<i-1;            return 0;        }    }    memcpy(b,a,sizeof b); sort(b+m+1,b+n+1,cmp);    a_xb=m+1; b_xb=m+1;    a[n+1].x=a[n+1].y=MAX; b[n+1].x=b[n+1].y=MAX;    ans=m;    while (a_xb<=n||b_xb<=n){        if (a[a_xb].y+h.top()<b[b_xb].x){            s+=a[a_xb].y+h.top();            h.pop();            h.push(a[a_xb].x-a[a_xb].y);            f[a[a_xb].z]=1;        }        else{            s+=b[b_xb].x;            f[b[b_xb].z]=1;        }        if (s>k){            cout<<ans;            return 0;        }        else ans++;        while (f[a[a_xb].z]&&a_xb<=n) a_xb++;        while (f[b[b_xb].z]&&b_xb<=n) b_xb++;    }    cout<<ans;    return 0;}
0 0
原创粉丝点击