JZOJ 5461 购物 —— 贪心
题目:https://jzoj.net/senior/#main/show/5461


贪心,原来想了个思路,优先选优惠价最小的 K 个,然后其他按原价排序遍历;
如果当前物品没选过,原价选上,如果选过,考虑把它换成原价,然后把优惠价最小的下一个选上;
但这样做是75分,没考虑 替换没选过的物品 和 比较替换后是否更优;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=5e4+;
int n,K,cnt;
ll m,ans;
bool vis[maxn];
struct N{
int w,t,id;
bool operator < (const N &y) const
{return w>y.w;}
}p[maxn];
priority_queue<N>q;
bool cmp(N x,N y){return x.t<y.t;}
int main()
{
freopen("shopping.in","r",stdin);
freopen("shopping.out","w",stdout);
scanf("%d%d%lld",&n,&K,&m);
for(int i=;i<=n;i++)scanf("%d%d",&p[i].w,&p[i].t);
sort(p+,p+n+,cmp);
for(int i=;i<=n;i++)p[i].id=i,q.push(p[i]);
for(int i=;i<=K&&i<=n;i++)
{
if(ans+p[i].t>m)break;
vis[i]=; cnt=i; ans+=p[i].t;
}
if(cnt==n){printf("%d\n",n); return ;}
while(q.size())
{
int x=q.top().id,w=q.top().w,t=q.top().t; q.pop();
if(!vis[x])
{
if(ans+w>m)continue;
ans+=w; cnt++;
}
else
{
if(ans-p[x].t+p[x].w+p[K+].t>m)continue;
ans=ans-p[x].t+p[x].w+p[K+].t; K++; cnt++;
vis[x]=; vis[K]=;
}
}
printf("%d\n",cnt);
return ;
}
原
正解是直接把选中物品的 原价 - 优惠价 放入小根堆,然后其他物品按原价排序,直接判断、替换;
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=5e4+;
int n,K,cnt;
ll m,ans;
bool vis[maxn];
struct N{int w,t,id;}p[maxn];
priority_queue<int>q;
bool cmp(N x,N y){return x.t<y.t;}
bool cmp2(N x,N y){return x.w<y.w;}
int main()
{
// freopen("shopping.in","r",stdin);
// freopen("shopping.out","w",stdout);
scanf("%d%d%lld",&n,&K,&m);
for(int i=;i<=n;i++)scanf("%d%d",&p[i].w,&p[i].t),p[i].id=i;
sort(p+,p+n+,cmp);
for(int i=;i<=K&&i<=n;i++)
{
if(ans+p[i].t>m)break;
cnt=i; ans+=p[i].t;
q.push(p[i].t-p[i].w); vis[p[i].id]=;
}
if(cnt==n){printf("%d\n",n); return ;}
sort(p+,p+n+,cmp2);
for(int i=,x;i<=n;i++)
{
if(vis[p[i].id])continue;
if(q.size())
{
x=-q.top();
if(x+p[i].t>p[i].w&&ans+p[i].w<=m)ans+=p[i].w,cnt++;
else if(x+p[i].t<=p[i].w&&ans+x+p[i].t<=m)ans+=x+p[i].t,cnt++,q.pop(),q.push(p[i].t-p[i].w);
}
else if(ans+p[i].w<=m)ans+=p[i].w,cnt++;
}
printf("%d\n",cnt);
return ;
}
TJ
但这样总感觉不对,因为按原价排序并不能保证替换最优;
这里就是反例:
6 3 15
10 3
8 4
7 5
5 1
4 2
3 2
按这样的做法,会先选后3个物品,然后按 1,2,3 把前三个物品排序;
然后把物品6换成原价购买,优惠价购买物品 3;
之后就不能买了,输出4;
但实际上应该是优惠价购买物品 1,2,4,原价购买物品 5,6,答案是5;
所以应该采用别的贪心策略,看到了一种很好的:https://blog.csdn.net/qq_40448823/article/details/81488195 (不过这篇博客贴错题面了囧)
所有物品都按优惠价排序,同时开了一个原价购买的大根堆,存已经原价买下的东西的原价;
先买 K 个优惠价的,然后从优惠价排序的顺序继续往后看,每次去掉优惠买中 原价 - 优惠价 最小的一个,优惠价买下一个;
然后回头看看能否原价买上去掉的这个东西,能就原价买上,不能就去原价物品堆里看看,如果能替换一下使花钱更少,那么就替换一下;
而如果优惠价购买下一个不如原价购买下一个优,那么原价购买下一个,同样进行替换的判断;
然后就能过掉上面的数据了,主要是因为优惠价部分排序满足,原价部分用大根堆替换来满足;
不过数据太水,也不知道这个做法是否完美无瑕,看样子应该没问题,先放到这里吧。
代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
typedef long long ll;
int const maxn=;
int n,K,ans;
ll sum,m;
struct N{
int w,t,c;
bool operator < (const N &y) const
{return c>y.c;}
}p[maxn];
priority_queue<N>Q;
priority_queue<int>q;
bool cmp(N x,N y){return x.t<y.t;}
int main()
{
freopen("shopping.in","r",stdin);
freopen("shopping.out","w",stdout);
scanf("%d%d%lld",&n,&K,&m);
for(int i=;i<=n;i++)scanf("%d%d",&p[i].w,&p[i].t),p[i].c=p[i].w-p[i].t;
sort(p+,p+n+,cmp);
for(int i=;i<=n;i++)
{
if(Q.size()<K&&sum+p[i].t<=m){sum+=p[i].t; ans++; Q.push(p[i]);}//Q是按差价排序的堆
else if(Q.size()==K)//其他物品是按优惠价排序的
{
N x=Q.top();
if(x.c+p[i].t<=p[i].w)//优惠价购买较优
{
Q.pop(); Q.push(p[i]);
sum=sum-x.t+p[i].t;//先优惠价买上
if(sum+x.w<=m){sum+=x.w; ans++; q.push(x.w);}//可以原价买原来那个 //q是原价购买了的堆
else if(q.size()&&q.top()>x.w){sum=sum-q.top()+x.w; q.pop(); q.push(x.w);}
//不能买了,换掉之前原价购买的一个物品,可以更优
}
else if(sum+p[i].w<=m){sum+=p[i].w; ans++; q.push(p[i].w);}//原价购买
else if(q.size()&&q.top()>p[i].w){sum=sum-q.top()+x.w; q.pop(); q.push(x.w);}//不能买了,替换更优
}
}
printf("%d\n",ans);
return ;
}
JZOJ 5461 购物 —— 贪心的更多相关文章
- JZOJ 5461. 【NOIP2017提高A组冲刺11.8】购物
5461. [NOIP2017提高A组冲刺11.8]购物 (File IO): input:shopping.in output:shopping.out Time Limits: 1000 ms ...
- JZOJ 5459 购物
Description X 城的商场中,有着琳琅满目的各种商品.一日,小X 带着小Y 前来购物,小Y 一共看中了n件商品,每一件商品价格为Pi.小X 现在手中共有m个单位的现金,以及k 张优惠券.小X ...
- JZOJ.1150【贪心算法】IQ
欢迎转载,请附上原链接https://www.cnblogs.com/Code-Garden/p/11276741.html(也没人会看) 一道对我来说较难的贪心题 题目描述 根据世界某权威学会的一项 ...
- JZOJ.1153【贪心算法】硬币交换
好难啊!!! 可聪明的我还是解出来了!(逃 题目描述 小z最近迷上了一款游戏――To Be A Farmer,他在游戏中控制的人物是一个叫FZ的Farmer.FZ身上有G1个金币.S1个银币和B1个铜 ...
- JZOJ 1154. 【GDOI2003】购物
1154. [GDOI2003]购物 (Standard IO) Time Limits: 1000 ms Memory Limits: 65536 KB Description GDOI商场推出优惠 ...
- [jzoj 4879] [NOIP2016提高A组集训第11场11.9] 少女觉 解题报告 (贪心)
题目链接: http://172.16.0.132/senior/#main/show/4879 题目: 在幽暗的地灵殿中,居住着一位少女,名为古明地觉.据说,从来没有人敢踏入过那座地灵殿,因为人们恐 ...
- JZOJ 4611. 【NOI2016模拟7.11】接水问题 (贪心+A*+可持久化线段树)
Description: https://gmoj.net/senior/#main/show/4611 题解: 先把A从大到小排序,最小的由排序不等式显然. 考虑类似第k短路的A*的做法. 定义状态 ...
- [jzoj]1729.blockenemy
Link https://jzoj.net/senior/#main/show/1729 Description 你在玩电子游戏的时候遇到了麻烦...... 你玩的游戏是在一个虚拟的城市里进行,这个城 ...
- 洛谷P1658 购物
题目戳 题目描述 你就要去购物了,现在你手上有N种不同面值的硬币,每种硬币有无限多个.为了方便购物,你希望带尽量少的硬币,但要能组合出1到X之间的任意值. 输入输出格式 输入格式: 第一行两个数X.N ...
随机推荐
- tp系统常量
ThinkPHP的公共入口文件里定义了系统常量 RUNTIME_PATH----系统运行时目录 LIB_PATH-----------系统核心类库目录 CORE_PATH--------Think类库 ...
- [转]Linux中进程内存与cgroup内存的统计
From: http://hustcat.github.io/about/ Linux中进程内存与cgroup内存的统计 在Linux内核,对于进程的内存使用与Cgroup的内存使用统计有一些相同和不 ...
- Bullet:关于ORACLE中的HASH JOIN的参数变化
Oracle在7.3引入了hash join. 但是在Oracle 10g及其以后的Oracle数据库版本中,优化器,实际是CBO,也是因为HASH JOIN仅适用于CBO,在解析目标SQL时是否考虑 ...
- NFS文件服务
安装NFS服务 Yum install nfs-utils –y 2.关闭防火墙 service iptables stop 3./etc/exports NFS服务配置文件 /home/share ...
- linux which-查找并显示给定命令的绝对路径
推荐:更多Linux 文件查找和比较 命令关注:linux命令大全 which命令用于查找并显示给定命令的绝对路径,环境变量PATH中保存了查找命令时需要遍历的目录.which指令会在环境变量$PAT ...
- webpack3 + vue 添加 serviceWorker
新的vue脚手架已经可以自带pwa了,本文主要针对旧版的webpack. 先装三个插件: $npm i register-service-worker sw-precache-webpack-plug ...
- SQL学习笔记:库和表的创建
目录 创建和删除数据库 创建和删除表 添加.修改和删除字段 创建和删除数据库 CREATE DATABASE justForLearn; DROP DATABASE justForLearn; 创建和 ...
- 【01】CSS3 Gradient 分为 linear-gradient(线性渐变)和 radial-gradient(径 向渐变)(转)
CSS3 Gradient 分为 linear-gradient(线性渐变)和 radial-gradient(径 向渐变).而我们今天主要是针对线性渐变来剖析其具体的用法.为了更好的应用 CSS3 ...
- [置顶]
Linux学习总结(20)——Linux 文件夹结构和作用
/bin 二进制可执行命令 /dev 设备特殊文件 /etc 系统管理和配置文件 /etc/rc.d 启动的配置文件和脚本 /home 用户主目录的基点,比如用户user的主目录就是/home/us ...
- Leetcode 122.买卖股票的最佳时机II
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格. 设计一个算法来计算你所能获取的最大利润.你可以尽可能地完成更多的交易(多次买卖一支股票). 注意:你不能同时参与多笔交易(你必须在再次 ...