nssl1148,jzoj5461-购物【可撤回贪心,堆】
生活随笔
收集整理的這篇文章主要介紹了
nssl1148,jzoj5461-购物【可撤回贪心,堆】
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
正題
jzoj題目鏈接:https://jzoj.net/senior/#main/show/5461
題目大意
有n個物品,m元,k個打折券。
每個物品打折前pip_ipi?元,打折后qiq_iqi?元,求最多能買多少物品。
解題思路
用可撤回貪心。
先將p和q分開排序,然后前k個都用打折劵。之和我們考慮一個新的東西如果必須打折的話,那么就相當于用pmini?qminip_{min\ i}-q_{min\ i}pmin?i??qmin?i?元買一個打折卷,所以我們用堆用最大的進行比較買不買打折券好
code
#include<cstdio> #include<algorithm> #include<queue> #define N 100010 using namespace std; struct node{long long w,num; }q[N],p[N]; long long n,k,m,ans; priority_queue <int> K; bool f[N]; bool cmp(node x,node y) {return x.w<y.w;} int main() {scanf("%lld%lld%lld",&n,&k,&m);for(long long i=1;i<=n;i++){scanf("%lld%lld",&p[i].w,&q[i].w);p[i].num=q[i].num=i;}sort(p+1,p+1+n,cmp);sort(q+1,q+1+n,cmp);//分開排序long long j=1;for(long long i=1;i<=n;i++){if(k)//前k個全要{if(m>=q[i].w){m-=q[i].w;f[q[i].num]=true;K.push(q[i].w-p[q[i].num].w);ans++;k--;}}else{while(f[j]&&j<n)j++;//走到沒有用過的if(m>=min(p[j].w,q[i].w-K.top()))//買的起{m-=min(p[j].w,q[i].w-K.top());if(p[j].w>q[i].w-K.top()){m-=q[i].w-K.top();K.pop();K.push(q[i].w-p[q[i].num].w);//壓入堆}else j++;//下一個最小的ans++;//多買一個}}}printf("%lld",ans); }總結
以上是生活随笔為你收集整理的nssl1148,jzoj5461-购物【可撤回贪心,堆】的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 编程要求电脑配置(编程 电脑配置)
- 下一篇: nssl1149,jzoj5455-拆网