1. 程式人生 > >2018年9月15日提高組模擬賽 T1 購物

2018年9月15日提高組模擬賽 T1 購物

大意

給定n件商品,現在你有k張降價券,可以讓ai降至bi在購買金額不超過m最多能購買的物品數量

思路

首先顯然可以發現,用降價券是永遠比不用要好的,所以我們在一開始優先選擇讓降價後代價更低的,然後再依次補上,這種演算法是存在漏洞的,所以只能拿80分

若要拿一百分,通過觀察發現,有的時候一些本價本來就很低的商品用降價券是有點浪費的,我們完全可以話費的代價換一張降價券給另一件沒有被降價的商品,而顯然另一件商品的代價必須要小於之前我們說的代價才能交換

這就是一種新的思想,可撤銷貪心!

程式碼

#include<iostream>
#include<cstdio> #include<queue> using namespace std;int n,k,p[150001],q[150001],nused;long long m; bool used[150001]; struct node{long long num;int id;}; priority_queue<node>qp,qq; priority_queue<long long,vector<long long>,greater<long long> >cz; inline bool operator <(node x,node y){return
x.num>y.num;}//按照價值從小到大排 signed main() { cin>>n>>k>>m; for(register int i=1;i<=n;i++) scanf("%d%d",p+i,q+i),qp.push((node){p[i],i}),qq.push((node){q[i],i});//qp為降價前的,qq為降價後的 for(register int i=1;i<=k;i++) cz.push(0ll);//cz為差值,我們一開始假設所有的差值為0,這樣也就是假設所有能用降價券的商品都用了降價券 while
(m>0&&nused<n) { while(used[qq.top().id]) qq.pop(); while(used[qp.top().id]) qp.pop();//如果這些商品已經買走了則彈出 if(cz.top()+qq.top().num<qp.top().num)//若差價是要下於另一件商品的原價的,把優惠券給另一件商品 { node x=qq.top(); long long cost=cz.top()+x.num;//計算代價 if(m<cost) break;//買不起就退出吧 m-=cost;//買了 cz.pop(); cz.push(p[x.id]-q[x.id]);//新增差值 used[x.id]=true;//標記已經買了 } else//否則不換 { node x=qp.top(); long long cost=x.num;//直接把這個商品買走 if(m<cost) break;//買不起別買了 m-=cost;//買走 used[x.id]=true;//標記已經被買走了 } nused++;//多買了一件 } printf("%d",nused);//輸出 }