2018年9月15日提高組模擬賽 T1 購物
阿新 • • 發佈:2018-12-10
大意
給定件商品,現在你有張降價券,可以讓降至在購買金額不超過最多能購買的物品數量
思路
首先顯然可以發現,用降價券是永遠比不用要好的,所以我們在一開始優先選擇讓降價後代價更低的,然後再依次補上,這種演算法是存在漏洞的,所以只能拿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);//輸出
}